【问题标题】:Issue preventing GCC from optimizing out global variable阻止 GCC 优化全局变量的问题
【发布时间】:2016-01-25 21:40:27
【问题描述】:

我正在为 STM32F105RC 处理器使用 ARM-GCC v4.9(2015-06-23 发布)。
我搜索了 stackoverflow.com,发现这个是为了试图说服 gcc not 优化全局变量,如下所示:

static const char AppVersion[] __attribute__((used)) = "v3.05/10.oct.2015";

然而,令我惊讶,编译器优化掉了 AppVersion 变量!
顺便说一句:我正在使用优化级别 -O0(默认)。
我也尝试使用 volatile 关键字(如其他线程所建议的那样),但它也不起作用:(
我已经尝试过(void)AppVersion;,但它不起作用...
智能编译器!?我想太聪明了……

与此同时,我在代码中的某个地方使用了printf(AppVersion);,只是为了能够保留版本...但这是一个粗鲁的解决方案:(
所以,问题是:是否有任何 other 技巧可以完成这项工作,即防止版本被 GCC 优化掉?

[编辑]:
我也试过这样(即没有static):

const char AppVersion[] __attribute__((used)) = "v3.05/10.oct.2015";

...它也没有用:(

【问题讨论】:

  • 试试 ( void )AppVersion;主要的某处。
  • @this : 我已经尝试过(void)AppVersion; 但它不起作用...
  • @dsi:我试过没有static,但它不起作用:(
  • 我正在考虑使用更新版本的编译器(何时可用)......但我想我不会得到不同的东西,对吧?可能是浪费时间...

标签: c variables gcc optimization arm


【解决方案1】:

不幸的是,我不知道执行此操作的 pragma。
然而,还有另一种解决方案。将 AppVersion 更改为:

static char * AppVersion = "v3.05/10.oct.2015";

并添加:

__asm__ ("" : : "" (AppVersion));

到你的主要功能。

你看我删除了'used'属性,根据文档,这是一个函数属性。

其他解决方案: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】:

    鉴于“静态”的存在,您的声明所做的只是要求编译器将表示字符串“v3.05/10.oct.2015”的字符的字节包括 在文件中的某个任意位置有一些命令,但不想告诉 任何人把它们放在哪里。鉴于编译器可以合法地编写 代码图像文件中某处的字节序列无论是否 出现在代码中的任何地方这样的声明真的不是很有用。到 可以肯定的是,这样的序列不太可能出现在代码中 完全是偶然的,因此扫描二进制图像可能有点 确定它出现在代码中的可靠方法,但一般来说 最好有一些方法来肯定地确定字符串的位置 可以找到。

    如果字符串没有声明为静态的,那么编译器需要告诉 链接器在哪里。由于链接器通常输出名称和 各种地方的所有符号的地址,包括符号表, 调试信息文件等,可以以多种方式使用 链接器对此一无所知,它可能能够判断出未使用符号 在代码中,但通常不知道是否有其他 实用程序可能希望在符号表中找到它并使用它。一个说符号被“使用”的指令将告诉链接器,即使它不知道任何对该符号感兴趣的东西,但链接器对它一无所知的更大宇宙中的某些东西对它感兴趣。

    每个编译单元通常会向 链接器并说“这里有一些东西;我需要一个符号作为它的开头,但是 我可以从中计算出所有内部结构的所有地址”。链接器 无法知道实际使用了此类 blob 的哪些部分,因此它 没有选择,只能逐字接受整个事情。如果编译器是 要在其 blob 中包含未使用的静态声明,他们会通过 到输出文件。另一方面,编译器知道,如果它不 为该 blob 中的某物导出符号,下游没有其他人会 能够找到它,无论该对象是否被包括在内;因此,会有 通常,能够包含这样的 blob 并没有什么好处,编译器编写者通常必须有理由提供一个功能来强制包含这样的内容。

    【讨论】:

    • 是的,这真的很有意义...我不是 100% 确定,但我想我(几天前)尝试过(几天前)不使用static,但它没有用...但是好的,我不想悲观,明天再试,现在更关注代码等。
    • @groenhen:我对 gcc 工具链不是很熟悉,但通常需要做的是告诉链接器某处对符号感兴趣。这通常可以通过在源代码中使用某种指令或通过将命令行选项传递给链接器来完成。
    • 老实说,我更喜欢在源代码中添加编译指示/属性,而不是乱用命令行链接器选项:)
    • @groenhen:哪种方法更好可能取决于您打算对符号做什么。如果它被构建脚本中的某些东西使用,那么将它作为该构建脚本传递给编译器的命令行选项的一部分可能是明智的。无论如何,我建议您同时查看编译器文档和链接器文档,因为两者都需要协调工作。
    • 知道它在哪里被剥离会很有用;即它是编译器问题还是链接器问题?如果您使用“仅编译”(-c)运行该符号是否存在于结果对象中? (它必须是非静态的——即使在 -O0 中,未使用的静态事物也受编译器的支配)。
    【解决方案3】:

    似乎使用自定义部分也可以。

    代替

    __attribute__((used))
    

    试试

    __attribute__((section(".your.section.name.here")))
    

    链接器不会触及它,strip 命令也不会。

    【讨论】:

      猜你喜欢
      • 2021-12-10
      • 2017-09-20
      • 1970-01-01
      • 2011-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多