2

我在我的代码中将以下字符串声明为常量。目的是提供一种在编译输出中存储简单元数据的粗略而简单的方法。

const char myString1[] ="abc123\0";
const char myString2[] = {'a','b','c','1','2','3','\0'};

当我使用十六进制编辑器检查输出时,我看到了其他字符串常量,但没有出现“abc123”。这使我相信启用的优化会导致无法编译这些行,因为它们从未在程序中被引用。

有没有办法在代码中强制编译,或者用另一种方式(在代码中)将此元数据放入二进制文件中?我不想对二进制后编译进行任何操作,目标是使其尽可能简单。

编译器标志

-O2 -g -Wall -c -fmessage-length=0 -fno-builtin -ffunction-sections -mcpu=cortex-m3 -mthumb

4

4 回答 4

3

我认为您正在寻找以下used属性:

'使用'

附加到变量的此属性意味着即使看起来未引用该变量,也必须发出该变量。

当应用于 C++ 类模板的静态数据成员时,该属性还意味着如果类本身被实例化,则该成员将被实例化。

像这样应用

__attribute__((used))
const char myString1[] ="abc123\0";
__attribute__((used))
const char myString2[] = {'a','b','c','1','2','3','\0'};

鉴于您发布的编译器标志,它几乎可以肯定是链接器。该-ffunction-sections标志将每个定义放入目标文件中自己的部分。这允许链接器轻松确定未引用数据项或函数并将其从最终二进制文件中省略。

于 2012-09-13T20:20:16.030 回答
1

使用 binutilsstrings命令查看这些字符串是否存在于您的二进制文件中。

如果它们已被优化,您可以在声明它们时尝试使用volatile限定符。请注意,如果即使使用volatile限定符也不使用它们,某些编译器仍然可以优化它们。

于 2012-09-13T20:10:47.203 回答
1

我想出了一个使用属性并涉及修改链接脚本的解决方案。

首先,我定义了一个名为“.metadata”的自定义部分。

__attribute__ ((section(".metadata")))

然后,在SECTIONS.ld 脚本的块中,我添加了一个即使不使用KEEP(*(.metadata))它也会强制链接器包含.metadata

.text :
{
    KEEP(*(.isr_vector))
    KEEP(*(.metadata))
    *(.text*)
    *(.rodata*)

} > MFlash32

笔记

我发现__attribute__关键字必须与变量位于同一行,否则它实际上不会出现在二进制文件中,尽管 .metadata 部分确实出现在内存映射中。

于 2012-09-13T22:25:37.893 回答
0

如果你在文件范围内有这些变量,编译器必须提供字符串,因为他不知道它们是否会被不同的编译单元使用。因此,放置这些变量的任何“.o”文件都必须包含该字符串。

现在,一个聪明的链接器可以决定最终二进制文件不需要这些常量。(不过,我从未观察到。)如果您的平台是这种情况,您应该在“假设”路径上使用变量,实际上程序永远不会采用该变量。就像是

int main(int argc, char*argv[]){
  switch (argv[0][0]) {
    case 1: return myString1[argv[0][1]];
    case 2: return myString2[argv[0][1]];
  }
  ...
}
于 2012-09-13T21:05:25.287 回答