防止gcc删除未使用的变量

Ing*_*rdt 16 c gcc

在我们的源文件中,我们通常有一个类似的版本字符串:

static const char srcvers[] = "VERSION/foo.c/1.01/09.04.15";
Run Code Online (Sandbox Code Playgroud)

当该字符串未被优化时,它在某些情况下非常有用,因为可以通过简单地调用来确定链接到可执行文件的每个源文件的版本strings a.out | grep VERSION.

不幸的是,它 gcc优化(使用'-O').所以我的问题是,是否有一种简单的方法(编译器开关会很棒)使gcc保持该变量(其名称始终相同)而不关闭任何其他优化.

编辑

在我看来,这个问题与那个不同的是,我希望找到一个解决方案,我不必触及成千上万的源文件.

Dog*_*ert 28

您可以使用__attribute__((used))gcc(也可以在clang中工作)特定(我看到问题已标记gcc)属性:

附加到函数的此属性意味着即使看起来函数未被引用,也必须为函数发出代码.例如,仅在内联汇编中引用该函数时,这很有用.

来自https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

演示:

$ cat a.c
static const char srcvers[] __attribute__((used)) = "VERSION/foo.c/1.01/09.04.15";
$ gcc -O3 -c a.c
$ strings a.o
VERSION/foo.c/1.01/09.04.15
Run Code Online (Sandbox Code Playgroud)

你可以使用一些#ifs和#defines来制作这个terser,也可以在不支持这个扩展的编译器上编译.

  • ```__attribute__((used))``` 使用全局变量对我不起作用(文档确实暗示它只适用于函数)(arm-none-eabi gcc 7),但将符号放在不同的部分通过```__attribute__((section(".data")))```确实有效。这大概是因为链接器只能在通过 `-fdata-sections` 给它们自己的部分时剥离符号。我不喜欢它,但它奏效了。 (3认同)
  • 尽管文档摘录描述了此属性与函数的用法,但是同一属性也可以与变量一起使用,前提是它们具有静态存储(如本例所示). (2认同)

Sam*_*nko 5

据我了解您的问题,您需要在不触及源的情况下将版本字符串添加到每个目标文件.它可以使用下一种方式完成.

创建头文件,例如include/version.h:

#ifndef VERSION_H
#define VERSION_H

static const char _ver[] __attribute__((used)) = "VERSION/foo.c/1.01/09.04.15";

#endif /* VERSION_H */
Run Code Online (Sandbox Code Playgroud)

然后在你的Makefile(或任何你的构建系统)添加下一个gcc标志:

CPPFLAGS += -include include/version.h
Run Code Online (Sandbox Code Playgroud)

当然应该传递给gcc,例如:

%.o: %.c
    $(CC) $(CFLAGS) $(CPPFLAGS) -o $(*).o -c $(*).c
Run Code Online (Sandbox Code Playgroud)

现在您可以观察_ver编译到每个目标文件的字符串:

$ objdump -DS src/main.o | grep _ver
Run Code Online (Sandbox Code Playgroud)

哪个会告诉你这样的事情:

Disassembly of section .rodata._ver:
00000000 <_ver>:
Run Code Online (Sandbox Code Playgroud)