您的位置:首页 > 其它

gcc 杂项

2014-05-04 09:28 78 查看
----------------------------------------

gcc 的一些技巧。

----------------------------------------

查找,查看连接的库位置: gcc -v

预处理过程:gcc -E, 可以看到头文件及宏展开后的形态。

查找,查看宏定义位置,

cpp -dD 可以显示宏定义过程。 -dM 还能显示预定义宏。 cpp -dM /dev/null 显示纯系统定义宏

虽然我不能确定gcc 是否调用了cpp 来进行预处理(也许不是), 但把gcc 换成cpp, 再加上-dD 选项

确实可以达到目的。然后你可以按提示直接去浏览文件,以解除心中的疑惑!

什么都不用动,把gcc 换成 cpp, 加上-g3 选项,可以看到细节。

还有一个有用的技巧。向gcc 传递了-Wa,-alh 参数,生成了汇编列表文件,使我很欣慰!

不仅.s文件,.c 文件也可以,令我惊讶。用法很简单。有什么用呢?有用,...慢慢再说。

----------------------------------------

gcc -g3 能够使我们在gdb 中看到宏定义和宏值。

gdb 中: 对宏的用法

p XXXX

info macro XXXX

macro expand XXXX

----------------------------------------

gcc 生成map 文件,

-Wl,-map,<map-file>

传给ld 的选项 -Wl 后面的参数不能有空格。

举例:

gcc -o op_test op_test.o end.o -Wl,-Map,1.map

----------------------------------------

gcc 生成prof. gcc -pg

man gcc 有对-pg 选项的说明, gcc --help 没有对该项的说明

需要运行程序,正常退出,才能生成gmon.out, 供gprof 分析

gprof (默认为-p -q) -p 统计,本职功能, -q call graph, -b 简短的,不输出对各参数的解释。

-A[symspec], 只关联指定函数

用法举例:

gprof ./test gmon.out -b

生成调用图片:

gprof ./test | gprof2dot.py -n0 -e0 | dot -Tpng -o output.png

gprof2dot 默认是部分函数调用图 -n0.5, 即影响小于5%的函数就不显示了。

-n0 -e0 显示全部函数调用,当然这样可能因为内容太多,显示比较混乱。

-s 选项, 不显示诸如模板,函数入口参数等,使函数名称显示更加简洁。

----------------------------------------

由以上命令可以解决程序中的符号定位问题。

gcc -M -MP -MF -MD -MT 是什么意思?

gcc -M 不是输出预处理结果,而是输出源文件的依赖关系,包括include 的头文件,

gcc -MF abc.Tpo 把依赖关系输出到指定的输出文件, 否则会输出到屏幕上, abc.Tpo是输出文件名

gcc -MP 对每一个头文件也生成 target.,这样当make 的时候,每个头文件必需存在,编译更严谨

上面三项常连用。

gcc -MD: 相当于 -M -MF, 使用了默认文件名--目标文件名加.d , 保存依赖关系

可见,它们都是为了target 的依赖关系而生。

gcc -MT: 指定一个新的target 名。

----------------------------------------

消除 warning: "unused parameter xxxx"警告

----------------------------------------

如下定义一个宏即可:

#define UNUSED(x) (void)x

举例:

UNUSED(argc);

UNUSED(argv);

----------------------------------------

在64位机器上,整形数不能直接转化为指针。提示如下警告:

cast to pointer from integer of different size

----------------------------------------

有时候由于参数定义等原因确实需要强制转换,如下形式可用。

先转为long, 再转为指针。

(void *)(long)int_value

~

----------------------------------------

判断gcc 到底连接的是哪一个库,是动态库还是静态库,库的全路径是什么?

我目前采用的办法是strace.

对于exe 或 或 so, 判断其动态库依赖关系可以用ldd,

例如:

[/pts/1@hjj ~/work/cube_httpd]$ ldd httpd

linux-vdso.so.1 => (0x00007fff0fdff000)

libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003a13c00000)

libc.so.6 => /lib64/libc.so.6 (0x0000003a13800000)

/lib64/ld-linux-x86-64.so.2 (0x0000003a13400000)

------------------------------------------------------------

问题. gcc 版本不一致出现的问题,查看gcc 版本,strings 命令

------------------------------------------------------------

./app_ref: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by ./app_ref)

软件编译时使用了较高版本的glibc: 要求glibc_2.14, 这是是gcc 4.6 编译的.

当前系统的glibc版本太低,

查看当前的glibc.

$ strings /lib64/libc.so.6 |grep -i glibc

GLIBC_2.2.5

GLIBC_2.2.6

GLIBC_2.3

GLIBC_2.3.2

GLIBC_2.3.3

GLIBC_2.3.4

GLIBC_2.4

GLIBC_2.5

GLIBC_2.6

GLIBC_2.7

GLIBC_2.8

GLIBC_2.9

GLIBC_2.10

GLIBC_2.11

GLIBC_2.12

GLIBC_PRIVATE

glibc 2.12

*** glibc detected *** %s: %s: 0x%s ***

发现最高支持到glibc 2.12.

这个是gcc 4.4 支持到的版本

降低app_ref 的gcc, 或升级本系统gcc, 问题可以解决.

----------------------------------------

volatile 变量: 禁止编译器优化选项。

----------------------------------------

例如:int i; for(i=0;i<1000;i++);

被优化为i=1000

mem[2]=0x1;mem[2]=0x2;mem[2]=0x3;

被优化为mem[2]=0x3;

大部分优化是可行的,它缩短了执行时间,同样达到了效果。但有时不是我们需要的。

void main(int argc,char *argv[])

{

int i = 10;

int a = i;

printf("i=%d",a);

//下面汇编语句的作用就是改变内存中i的值,但是又不让编译器知道

__asm

{

mov dword ptr[ebp-4],20h

}

int b = i;

printf("i=%d",b);

}

如上代码,编译器可能把b 直接优化成10. 因为编译器可能把i 读入寄存器中,例如%edx

然后把%edx 付给内存a, 又付给内存b, 它不知道内存i 内容已经变了。这不是我们所要的

告诉编译器i 是volatile, 编译器将不对i进行优化,将忠实于代码执行流程。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: