我正在使用ARM-GCC v4.9(2015-06-23发布)用于STM32F105RC处理器。
我已经搜索了stackoverflow.com并且我发现了这一点,以便试图说服gcc 而不是来优化全局变量,如下所示:
static const char AppVersion[] __attribute__((used)) = "v3.05/10.oct.2015";
然而,令我真正意外,编译器优化了AppVersion变量!
顺便说一句:我使用的是优化级别 -O0 (默认)
我也尝试使用volatile
关键字(如其他主题所示),但它也没有工作:(
我已经尝试了(void)AppVersion;
但它没有工作......
智能编译器!?太聪明了,我想......
与此同时,我在代码中使用printf(AppVersion);
某个地方,只是为了能够保留版本......但这是一个粗野的解决方案:(
所以,问题是:是否有任何其他技巧可以完成这项工作,即保持版本不会被GCC优化掉?
[编辑]:
我也尝试过这样(即没有static
):
const char AppVersion[] __attribute__((used)) = "v3.05/10.oct.2015";
......它也没有工作:(
答案 0 :(得分:5)
鉴于存在" static",您的所有声明都要求编译器包含表示字符串字符的字节" v3.05 / 10.oct.2015"在 在文件中的某个任意位置有一些订单,但不用费心去辨别 任何放置它们的人。鉴于编译器可以合法地编写 代码图像文件中的某个字节序列是否存在 出现在代码中的任何地方这样的声明真的不是很有用。至 可以肯定的是,这样的序列不太可能出现在代码中 完全是偶然的,所以扫描二进制图像可能有点 确定它出现在代码中的可靠方法,但一般来说它是 有一些肯定地确定字符串的方法要好得多 可能会找到。
如果字符串未声明为静态,则需要编译器告诉 链接器在哪里。由于链接器通常输出名称和 包括符号表在内的各种地方的所有符号的地址, 调试信息文件等可以以多种方式使用 链接器一无所知,它可能会告诉我们没有使用符号 在代码内,但一般不知道是否其他一些 实用程序可能期望在符号表中找到它并使用它。指示该符号是"使用"会告诉链接器即使它不知道任何对该符号感兴趣的东西,但是在更大的宇宙中,链接器对它一无所知并且对它感兴趣。
每个编译单元通常会向其提供一大堆信息 链接并说"这里有一些东西;我需要一个符号作为它的开头,但是 我可以从那个"计算所有内部的所有地址。链接器 无法知道这样一个blob的哪些部分实际被使用,所以它 别无选择,只能逐字接受整件事。如果编译器是 要在其blob中包含未使用的静态声明,他们必须完成它 到输出文件。另一方面,编译器知道它是否没有 为该blob中的某个东西导出符号,下游没有其他人会这样做 无论对象是否包括在内都能找到它;因此,会有 能够包含这样一个blob通常没什么好处,编译器编写者通常不得不提出强制这种包含的功能。
答案 1 :(得分:2)
不幸的是,我不知道这样做的实用工具 然而,有另一种解决方案。将AppVersion更改为:
static char * AppVersion = "v3.05/10.oct.2015";
并添加:
__asm__ ("" : : "" (AppVersion));
到您的主要功能。
你看我放弃了使用过的'属性,根据文档,这是一个函数属性。
其他解决方案:Does gcc have any options to add version info in ELF binary file?
虽然我觉得这个最容易。这基本上不会让编译器和链接器删除AppVersion,因为我们告诉它这个内联汇编使用它,即使我们实际上没有插入任何内联汇编。
希望你会感到满意。
作者: Andre Simoes Dias Vieira
原始链接:https://answers.launchpad.net/gcc-arm-embedded/+question/280104
答案 2 :(得分:0)
似乎使用自定义部分也有效。
而不是
__attribute__((used))
尝试
__attribute__((section(".your.section.name.here")))
链接器不会触及它,strip
命令也不会触及它。