C 代码片断
(重定向自C代码片断)
变长参数
void fatal(char *fmt, ...){
va_list argp;
fprintf(stderr, "Fatal: ");
va_start(argp, fmt);
vfprintf(stderr, fmt, argp);
va_end(argp);
fprintf(stderr, "\n");
exit(-1);
}
来源:Variable-Length Argument Lists
volatile
关键字
可用mmap(2)实现自动变化的变量。使用gcc加优化参数编译,则为死循环。注意 while
循环体必须为空。
#include<stdio.h>
#include<stdlib.h>
#include<sys/mman.h>
#include<unistd.h>
#include<fcntl.h>
int main(int argc, char **argv){
int *p;
int fd = open("test", O_RDWR);
if(fd < 0){
perror("open test");
exit(1);
}
p = mmap(NULL, 4, PROT_WRITE, MAP_SHARED, fd, 0);
if(p == MAP_FAILED){
perror("mmap");
exit(1);
}
close(fd);
while(*p != 3);
munmap(p, 4);
return 0;
}
辅助程序,它从外部来改变上一个程序变量 *p
的值
#include<stdio.h>
#include<stdlib.h>
#include<sys/mman.h>
#include<unistd.h>
#include<fcntl.h>
int main(int argc, char **argv){
int *p;
int fd = open("test", O_RDWR);
if(fd < 0){
perror("open test");
exit(1);
}
p = mmap(NULL, 4, PROT_WRITE, MAP_SHARED, fd, 0);
if(p == MAP_FAILED){
perror("mmap");
exit(1);
}
close(fd);
for(fd=0; 1; fd++){
*p = fd;
sleep(1);
}
munmap(p, 4);
return 0;
}
信号
收到信号时打印函数栈并退出:
void SetMyExceptionHandler(){
int signo;
for(signo = SIGHUP; signo < SIGUNUSED; signo++){
signal(signo, OnException);
}
}
void OnException(int signo){
if(signo == SIGCHLD)
return;
if(signo == SIGCONT)
return;
void *array[10];
size_t size;
char **strings = NULL;
size_t i;
size = backtrace(array, 10);
strings = backtrace_symbols(array, size);
if(strings){
FILE *fp = NULL;
fp = fopen("/home/lilydjwg/tmpfs/mb_crash.log", "w");
printf("Obtained %zd stack frames.\n", size);
if(fp){
fprintf(fp, "mb -- Get Signal No. %d\n", signo);
fprintf(fp, "Obtained %zd stack frames.\n", size);
}
for(i = 0; i < size; i++){
printf("%s\n", strings[i]);
if(fp)
fprintf(fp, "%s\n", strings[i]);
}
if(fp)
fclose(fp);
free(strings);
}
exit(128+signo);
}
来自fcitx的源代码。
LD_PRELOAD
重定向文件打开操作,使用 Lua 控制实际打开的文件:
#include <stdarg.h>
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
static int lib_initialized = 0;
static int (*orig_open)(const char*, int, mode_t) = 0;
static int (*orig_open64)(const char*, int, mode_t) = 0;
void lib_init();
void die(char *fmt, ...) {
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
fprintf(stderr, "\n");
fflush(stderr);
exit(-1);
}
int open(const char* file, int flags, mode_t mode) {
lib_init();
fprintf(stderr, "opening %s\n", file);
return orig_open(file, flags, mode);
}
int open64(const char* file, int flags, mode_t mode) {
lib_init();
fprintf(stderr, "open64ing %s\n", file);
return orig_open64(file, flags, mode);
}
void lib_init() {
void *libhdl;
char *dlerr;
if (lib_initialized) return;
if (!(libhdl=dlopen("libc.so.6", RTLD_LAZY)))
die("Failed to patch library calls: %s", dlerror());
orig_open = dlsym(libhdl, "open");
if ((dlerr=dlerror()) != NULL)
die("Failed to patch open() library call: %s", dlerr);
orig_open64 = dlsym(libhdl, "open64");
if ((dlerr=dlerror()) != NULL)
die("Failed to patch open64() library call: %s", dlerr);
lib_initialized = 1;
}
编译参数:
gcc -shared openredir.c -o openredir.so -ldl
大数及高精度计算
求第一个百万位的斐波那契数的各位数字之和:
#include<stdio.h>
#include<stdlib.h>
#include<gmp.h>
#include<mpfr.h>
int main(int argc, char **argv){
mpz_t a, b;
mpfr_t c, d;
mpz_inits(a, b, 0);
mpfr_inits(c, d, NULL);
unsigned long n = 4761900;
mpz_fib2_ui(a, b, n);
/* may be not so accurate... */
while(mpfr_set_z(c, a, MPFR_RNDA), mpfr_log10(d, c, MPFR_RNDA), mpfr_cmp_ui(d, 999999) < 0){
mpz_add(b, a, b);
mpz_swap(a, b);
n++;
}
char *r = mpz_get_str(NULL, 10, a);
int sum = 0;
int i;
for(i=0; i<1000000; i++){
sum += r[i] - '0';
}
mpz_out_str(stderr, 10, a);
printf("F(%lu)=%d\n", n, sum);
return 0;
}