【问题标题】:ARM, .COMMON section and -fno-common flagARM、.COMMON 部分和 -fno-common 标志
【发布时间】:2015-04-13 00:34:10
【问题描述】:

我正在尝试诊断问题。问题是如果我在程序的开头放置一个 printf(特别是 printf),我的程序可以正常工作,如果我不这样做,它就不会。该问题非常特定于读取我在 systick_handler 中递增的 systick 变量的循环。

如果我使用 -fno-common 进行编译,那么一切正常。为什么会有这种行为?

此外,我已经从链接描述文件中删除了 .COMMON 部分,因为它们使程序几乎翻了一番。无论如何,如果没有它们,一切都运行良好,但我怀疑当我使用默认 (-fcommon) 标志进行编译时,它们的缺失会以某种方式导致无限循环。我仍然在我的文件中看不到对 .COMMON 部分的引用。它必须只是来自 libc。

谁能解释发生了什么?

【问题讨论】:

  • 我不能提供一个,因为我不太确定问题是什么。我认为它在 libc 内部的某个地方,因为我根本没有使用 .common 部分。我通过使用 -fno-common 编译解决了这个问题,只是因为我首先省略了 .common 部分。但我不太确定这是否会导致将来出现一些未知问题,或者 -fno-common 是否永久解决了该问题。出现问题的平台我无法访问硬件调试界面,很遗憾。
  • 生成地图文件,看看 '.COMMON' 里放了什么。

标签: gcc linker arm ld


【解决方案1】:

当你使用 -fno-common 时,未初始化的全局变量会被 GCC 放置在 .bss 部分(哦,虽然手册上说的是数据)。如果您不使用该选项,它们将被放置在一个名为 COMMON 的特殊部分中。

如果您在链接描述文件中省略此部分,链接程序只会将其放入 RAM,可能会与其他数据重叠。您可以在地图文件中查看它。我只是用我的链接器脚本尝试过,发现 COMMON 的内容与我的情况下的堆放在同一内存区域。这意味着全局变量和任何分配的东西,例如 malloc 将相互覆盖。不要那样做。坏事会发生。

关于使用 -fno-common 并忽略 COMMON 的安全性:我假设库也可以包含 COMMON。即使您的代码因为使用 -fno-common 而不包含此部分,但这并不意味着链接器不需要处理它。只需在 *(.bss) 旁边添加 *(COMMON) 就可以安全了。如果内存消耗因此而增加,那是有充分理由的。

进一步阅读:

【讨论】:

  • 我不确定我观察到了什么,但是当尝试在 Apple 平台上进行测试时,Valgrind 点亮了一棵圣诞树。 Apple 要么 (1) 将一些已初始化的全局变量放在一起,要么 (2) 在它们所在的部分执行延迟初始化。我可以阻止 Valgrind 发现的唯一方法是在问题变量上添加 __attribute__((section ("nocommon")))。我们可能应该在命令行中添加-fno-common
猜你喜欢
  • 1970-01-01
  • 2020-12-18
  • 2019-04-03
  • 1970-01-01
  • 1970-01-01
  • 2016-01-25
  • 1970-01-01
  • 1970-01-01
  • 2016-02-24
相关资源
最近更新 更多