我在代码中将以下字符串声明为常量。目的是提供一种在编译输出中存储简单元数据的粗略而简单的方法。
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
答案 0 :(得分:3)
我认为您正在寻找used
属性:
`使用的“
此属性附加到变量,表示该变量 必须发出即使看起来变量不是 引用。
当应用于C ++类模板的静态数据成员时, 属性还意味着如果成员将被实例化 类本身是实例化的。
像
一样应用它__attribute__((used))
const char myString1[] ="abc123\0";
__attribute__((used))
const char myString2[] = {'a','b','c','1','2','3','\0'};
鉴于您发布的编译器标志,几乎可以肯定是链接器。 -ffunction-sections
标志将每个定义放入目标文件中的自己的部分。这允许链接器轻松确定未引用数据项或函数,并从最终二进制文件中省略它。
答案 1 :(得分:1)
使用binutils strings
命令查看二进制文件中是否存在这些字符串。
如果它们已经过优化,您可以在声明它们时尝试使用volatile
限定符。请注意,如果即使使用volatile
限定符也不使用它们,某些编译器仍然可以优化它们。
答案 2 :(得分:1)
我提出了一个使用属性的解决方案,并涉及修改链接脚本。
首先,我定义一个名为“.metadata”的自定义部分。
__attribute__ ((section(".metadata")))
然后,在.ld脚本的SECTIONS
块中,我添加了KEEP(*(.metadata))
,这将强制链接器包含.metadata
,即使它未被使用
.text :
{
KEEP(*(.isr_vector))
KEEP(*(.metadata))
*(.text*)
*(.rodata*)
} > MFlash32
注意强>
我发现__attribute__
关键字必须与变量位于同一行,否则它实际上不会显示在二进制文件中,尽管.metadata部分确实显示在内存映射中。< / p>
答案 3 :(得分: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]];
}
...
}