强制 GCC 放弃将某些全局变量清零

问题描述 投票:0回答:5

有什么方法可以告诉 GCC 不要将特定的全局数组初始化为零吗?

我想保留一大块内存来存储我的代码管理的大型数据结构,所以我说:

#define SIZE_16_MB 0x01000000
BYTE mChunkSpace[SIZE_16_MB];

问题是 crtinit() 需要一百万年才能将这个空间初始化为零,而且根本没有必要。

有什么方法可以强制它不初始化该空间吗?

目前,我正在对链接器不知道的内存地址进行硬编码,但这并不是一种特别可靠的处理方式。

此外,这是一个缓慢的嵌入式处理器(50MHz Microblaze),所以不要以为我正在谈论 PC。 确实需要很长时间才能将空间归零。

c gcc
5个回答
8
投票

您可以使用

gcc
属性将对象存储在另一个新的内存部分中,例如在
.noinit
内存部分中。

 BYTE mChunkSpace[SIZE_16_MB] __attribute__ ((section (".noinit")));

4
投票

尝试动态初始化:

BYTE* mChunkSpace = (BYTE*)malloc(SIZE_16_MB * sizeof(BYTE));

那么这个数据是未初始化的,等待你初始化。


2
投票

您在 SO 上得到的大多数答案将倾向于 Visual Studio 或 GCC,两者都在通用平台(即 PC,无论是 Windows 还是 Linux)上,并且会大量引用“标准说……” ,这些都不适用于小型嵌入式系统,除非您碰巧运行嵌入式 Linux 或 Windows CE。

ouah 的答案可能是最接近您需要的……如果您真正使用 GCC,也许正是您需要的。 由于您想要的内存块太大,可能会消耗系统内存的大部分,因此最好的选择是在构建的链接器命令文件中定义一个特殊部分,或者通过 C、C++ 或汇编文件中的链接器指令来定义。 这样做的语法因编译器而异。 如果您在源/汇编文件中使用链接器指令,则可能需要指定有关内存区域的读/写能力等的属性...或者如果 Microblaze 没有 MMU/内存控制器,则可能不需要指定。 您需要在该部分的开头放置一个链接器符号,并在您的 C 代码中使用“extern char symName[]”指令,以便您的 C 代码可以在重新定位中编译,链接器将用实际地址覆盖这部分。 根据编译器和体系结构,您可能还需要使用某种“far”属性声明 symName[] extern;我对 Microblaze 的了解还不够,无法对此发表任何评论。


0
投票

您需要在链接描述文件中声明一个具有“NOLOAD”属性的节。 如果您没有,请随意创建它,如下例所示。

在c文件中:

BYTE mChunkSpace[SIZE_16_MB] __attribute__ ((section (".my_noinit_section")));

在链接描述文件中:

MEMORY
{
   /*adapt to your device, I just write that to have a reasonably complete example*/
   RAM   (xrw)   : ORIGIN = 0x20000000, LENGTH = 32M
}
SECTIONS
{
   /*original linker script content here*/

   /*our new section without initialization*/
   .my_noinit_section (NOLOAD):
   {
      *(.my_noinit_section)
   } >RAM
}

根据您的原始链接器脚本,您可能需要更改“.my_noinit_section”的位置,可能在现有部分的中间。


-1
投票

该标准规定,在声明时未显式初始化的静态数据将被零初始化。 您可以通过自己将第一个元素初始化为非零值来避免运行时初始化:

#define SIZE_16_MB 0x01000000
BYTE mChunkSpace[SIZE_16_MB] = {1};

请注意,如果您指定

0
,编译器可能只会将其存储在
.bss
部分中,即,它仍将在运行时初始化。 它不必这样做,但不这样做就太愚蠢了。 所以现在你的数组被扔进了
.data
段。

当然,这将使生成的可执行文件变得更大(确切地说大约16MB),但内存不会在运行时初始化。 所以问题归结为什么对你来说最重要;将内存归零所需的时间,或最终的可执行文件大小?

© www.soinside.com 2019 - 2024. All rights reserved.