防止gcc删除未使用的变量

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

static const char srcvers[] = "VERSION/foo.c/1.01/09.04.15"; 

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

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

编辑

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

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

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

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

演示:

 $ cat ac static const char srcvers[] __attribute__((used)) = "VERSION/foo.c/1.01/09.04.15"; $ gcc -O3 -c ac $ strings ao VERSION/foo.c/1.01/09.04.15 

你可以使用一些#if#define来制作这个terser,也可以在不支持这个扩展的编译器上编译。

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

创建头文件,例如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 */ 

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

 CPPFLAGS += -include include/version.h 

当然它应该传递给gcc ,例如像这样:

 %.o: %.c $(CC) $(CFLAGS) $(CPPFLAGS) -o $(*).o -c $(*).c 

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

 $ objdump -DS src/main.o | grep _ver 

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

 Disassembly of section .rodata._ver: 00000000 <_ver>: 

将变量声明为volatile也可以提供帮助。 这就是为什么首先使用它,防止编译器对该变量进行任何优化。

由于似乎所有解决方案都需要在源代码中对版本字符串进行某种装饰,因此可能有助于定义包含所有必要语法的宏,然后在需要时在源文件或头文件中使用此宏:

 #define SRCVERSION(file, version, data) static const char _ver[] __attribute__((used)) = "VERSION/" file "/" version "/" date; 

然后在你的来源刚刚放

 SRCVERSION("foo.c", "1.01", "09.04.15") 

宏可以位于中央项目头文件中,也可以位于编译器的命令行中。

这样,如果您想要更改有关定义的内容,至少您不必再次触摸所有源文件。

请注意宏定义如何使用字符串连接来构建最终版本字符串。 它还包含最终的分号,因此您可以根据需要通过定义空宏来删除所有内容。

你担心gcc删除一个未使用的static char[]变量。 AFAIK,编译器是正确的。

其他答案提供了改善这一点的建议。 但是您不想更改数千个文件的源代码。

然后,您可能可能会更改您的构建(例如一些Makefile ),以便使用您的技巧(稍微错误,如此处所讨论的……)的每个此类源文件都不需要更改。 所以你可以专门调用GCC 。 你要

  static const char _ver[] __attribute__((used)); 

(这是一个声明,而不是定义)在其他任何事情之前编译。 将上面的行放在一些_declare_ver.h文件中,并使用 gcc -include _declare_ver.h命令(而不是gcc )进行gcc 。 如果使用make add

  CFLAGS += -include _declare_ver.h 

在你的Makefile

BTW,这是一个肮脏的把戏。 你应该考虑做一些更好的事情(遵循其他答案)。