Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 防止使用(从优化的副本)数据段到本地堆栈数据结构/阵列_C_Gcc_Optimization_Embedded - Fatal编程技术网

C 防止使用(从优化的副本)数据段到本地堆栈数据结构/阵列

C 防止使用(从优化的副本)数据段到本地堆栈数据结构/阵列,c,gcc,optimization,embedded,C,Gcc,Optimization,Embedded,我正在编写一些固件,需要在不使用数据段的情况下使用C代码。假设一个人远离地球人,这是非常简单的。至少我是这么想的 我编写了一些功能类似于以下代码的代码: void func() { int feature_set[][2] = { {feature0, 1}, {feature1, 0}, {feature2, 0} }; //Use 'feature_set' for some hardware init } 在我的特

我正在编写一些固件,需要在不使用数据段的情况下使用C代码。假设一个人远离地球人,这是非常简单的。至少我是这么想的

我编写了一些功能类似于以下代码的代码:

void func()
{
    int feature_set[][2] = {
        {feature0, 1},
        {feature1, 0},
        {feature2, 0}
    };

    //Use 'feature_set' for some hardware init
}
在我的特定用例中,
feature\u set
指的是我需要用于初始化的一些配置数据。因为我是在堆栈上创建这个数据集的,所以我希望在使用之前在堆栈上构造它。我意识到这会产生更多的指令,但在这种情况下,这是一个我可以接受的权衡

然而,在查看拆解后,我意识到它实际上是在做这样的事情:

mov ecx, <size>
lea edi, <stack addr>
lea esi, <somewhere in .data>
rep movs
mov-ecx,
lea edi,
李埃西,
雷普莫夫斯
很明显,编译器试图通过在
.data
中创建结构的常量版本并在需要时将其复制到堆栈来优化此操作


问题是:有没有办法防止这种情况?有没有办法告诉编译器不要将数据段用于此操作?更改优化级别可能会奏效,但我确实希望进行优化工作。。。只是没有特别针对这种构造

初始值设定项列表必须存储在某个地方,您不能在稀薄的空气中分配它。通常初始值设定项列表位于
.text
/
.rodata
中。然后,编译器可以通过将
功能集
放在
.data
而不是堆栈中来优化初始化,以更快地初始化它

无论如何,您可以这样做:

static const uint32_t FEATURE_SET [][2] = 
{
  {feature0, 1},
  {feature1, 0},
  {feature2, 0}
};
现在,阵列应该放在闪存中(
.rodata
或类似),否则链接器设置中的某些内容会出错

然后,如果需要堆栈上可修改的运行时版本:

uint32_t feature_set [ sizeof(FEATURE_SET) / sizeof(*FEATURE_SET) ] [2];
memcpy(feature_set, FEATURE_SET, sizeof feature_set);

另外,请确保不要使用奇怪的RAM调试版本,而是始终将程序下载到闪存,无论是调试版本还是发布版本。

如果您是在嵌入式系统上,您的编译器可能会有一些pre-proseesor指令,您可以使用它们来说明应该位于何处。如果这是用于闪存的固件,我将通过使用段属性或其他方式明确指示链接器,将只读数据放入flash中。哦,当然,让它成为
const
,也许这就是所需要的。什么是特性0等等?编译时常量还是运行时变量?@Lundin,整个数组是由常量构成的。这种情况下,我只有一个
text
部分。我的希望是,我可以不使用静态“初始值设定项”,让GCC输出更多的指令,在函数enter(即,常量移到堆栈上)时进行初始化。GCC与
-O0
的默认行为正是这样,但在项目I的其他地方是
-Os
-O3
。我发现我可以在文件范围内推送
-O0
选项(或者只包装函数),这也可以工作。我想这是可以的,但是让函数的行为完全依赖于优化级别并不是一个好的设计。也许我以后会的。这是一个爱好项目。