ARM、.COMMON 部分和 -fno-common 标志

ARM, .COMMON section and -fno-common flag

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

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

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

谁能解释一下这是怎么回事?

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

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

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

进一步阅读: