Surprise! LINUX/C语言中的一些惊人情况 2019-08-20 09:26:47

当然,这个“惊人”其实惊的是我。本文记录一些之前居然没有注意到LUNUX/C语言中的奇特现象。

1. 条件运算符的简化版

例如标准的做法:printf("%d\n", 1?1:0); 将输出1

而 gcc 允许简化为:printf("%d\n", 1?:0); ,即省略了第二个参数1,这时仍然会输出1!

即:当a为非零值时,a?:b 的值为a,否则为b。

注意1:该做法不是标准C语言允许的,而是gcc优化支持的,即仅在gcc环境有效。

注意2:a?a:ba?:b并不完全等价,例如 a++?a++:b 中a为真时a++将执行两次,而 a++?:b 中只会执行一次。

附:GCC的说明文档

2. sizeof后面的括号不是必须的

由于 sizeof 实际是个运算符(就跟+-*/差不多!),而不是函数,所以括号不是必须的。

例如 printf("%d\n", sizeof short); 能正常输出 2

3. 在每个函数进入和退出时执行指定的函数(像python装饰器一样!)

gcc的编译选项 -finstrument-functions,然后每个函数进入和退出时都会分别调用以下两个函数:

void __cyg_profile_func_enter(void *this_fn, void *call_site);
void __cyg_profile_func_exit(void *this_fn, void *call_site);

自己在代码中实现这2个函数即可。

如果不想让某些函数(例如函数test_func)调用这2个函数,可以用声明函数属性为 no_instrument_function

void test_func() __attribute__((no_instrument_function))
{
}

4. LD_PRELOAD实现库函数定义覆盖

使用LD_PRELOAD能使程序首先加载指定的库,例如执行:

shell>LD_PRELOAD=/tmp/libtest.so ./test

将预先加载/tmp/libtest.so并运行test程序,加入libtest.so中定义了malloc/realloc/calloc/free函数,则test中进行内存申请和释放时都会调用libtest.so中的函数(而不是C库中的),

可对test中内存情况进行跟踪调试。


创建于 2019-05-09 10:33:52
最后更新于 2019-08-20 09:26:47
昵称 密钥