标签:gcc

GCC 隐藏符号

日常被 GCC 折磨,GCC 链接报错,提示未定义符号。

排查编译流程确认该符号其最终被链接进入 third_party/wireshark/build/run/libwireshark.dylib。

而我最终又链接了 libwireshark.dylib。

并且确认该符号并非 static。

直接查找二进制文件也能够确认其符号已经被链接进入 dylib。

通过 nm 确认符号属性发现其为 t。

再次查看对应的 .o 确认其为 T。

那么该文本符号从 T 变成了 t 只能够是在链接阶段了。最后确认了 -fvisibility=hidden。

这个选项会将所有符号的默认可见性设置为隐藏,除非显式地声明为 default。这意味着,尽管在编译 .o 文件时符号是全局可见的,但在链接生成 .dylib 文件时符号变成了局部可见。

那为什么要这么做呢?

https://gitlab.com/wireshark/wireshark/-/blob/4aa814ac25a18ea48d4002351ed45d4b245b0c08/CMakeLists.txt#L1070-1104

主要目的是设置编译器默认隐藏符号,确保只有显式导出的符号才会在共享库(shared library)中可见。这可以帮助在更多的 Unix 系统上捕捉到符号导出失败的问题,而不仅仅是在 Windows 上。

https://gitlab.com...

聊聊 GCC 中的 int 类型和字节对齐

最近看到一个问题,在 64 位操作系统中。实际测试环境 Ubuntu 22.04,GCC 11。

问 sizeof(stuct test) =?当然我知道这道题想考察的 int/long 定义以及对齐问题,之前编码也不会太在意这类似问题,直接打印出来就行,但是作为考题这里有诸多不严谨地方。我们好好探索下。

不管三七二十一,直接编译打印。

显然地,这里 int 为4个字节,char 被4字节对齐。

看几个 GCC 选项

https://gcc.gnu.org/onlinedocs/gcc-9.5.0/gcc/x86-Options.html#x86-Options

看起来这里默认最大设置都是4字节对齐。

https://gcc.gnu.org/onlinedocs/gcc-9.5.0/gcc/Code-Gen-Options.html#Code-Gen-Options

显然地,这里的编译选项能够设置 long 类型和对齐。先看默认值。

这里能够设置 -m32 将 long 和指针类型设置为 4字节,但是对齐方式还是 4字节。

如下结论。

GCC 未使用函数、变量和文件优化策略

GCC 优化过于复杂,这里探索 GCC 对未使用的代码和变量以及文件的优化策略。

如下两个文件。

main.c 文件内容如下。

unused.c

  • 默认编译选项,通过可执行文件确定所有变量和函数都未优化。

  • -O1 -O2 -Os 选项,所有static 链接属性的变量和函数被用优化掉。

  • 为 static 链接属性的变量增加 __attribute__((used)) 属性。优化被抑制。

  • 增加 -Wl,--gc-sections 选项,所有的 unused.c 变量和函数,以及 main.c 中的变量全部被优化。

  • 同时使用 -Wl,--gc-sections 和 -O1。进一步优化掉 main.c 中的 static 函数,只剩下最后一个未使用的 extern 函数。

  • 同时使用 -Wl,--gc-sections 和 -O2 或者 -Os 。所有未使用的函数、变量全部被优化。

  • 或者额外指定 -ffunction-sections ,进一步把未使用的函数优化掉。

  • 对于--gc-sections ,通过设置 KEEP 链接抑制变量的优化。注意,并不能对函数使用属性。