有什么方法可以告诉 GCC 不要将特定的全局数组初始化为零吗?
我想保留一大块内存来存储我的代码管理的大型数据结构,所以我说:
#define SIZE_16_MB 0x01000000
BYTE mChunkSpace[SIZE_16_MB];
问题是 crtinit() 需要一百万年才能将这个空间初始化为零,而且根本没有必要。
有什么方法可以强制它不初始化该空间吗?
目前,我正在对链接器不知道的内存地址进行硬编码,但这并不是一种特别可靠的处理方式。
此外,这是一个缓慢的嵌入式处理器(50MHz Microblaze),所以不要以为我正在谈论 PC。 确实需要很长时间才能将空间归零。
您可以使用
gcc
属性将对象存储在另一个新的内存部分中,例如在 .noinit
内存部分中。
BYTE mChunkSpace[SIZE_16_MB] __attribute__ ((section (".noinit")));
尝试动态初始化:
BYTE* mChunkSpace = (BYTE*)malloc(SIZE_16_MB * sizeof(BYTE));
那么这个数据是未初始化的,等待你初始化。
您在 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 的了解还不够,无法对此发表任何评论。
您需要在链接描述文件中声明一个具有“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”的位置,可能在现有部分的中间。
该标准规定,在声明时未显式初始化的静态数据将被零初始化。 您可以通过自己将第一个元素初始化为非零值来避免运行时初始化:
#define SIZE_16_MB 0x01000000
BYTE mChunkSpace[SIZE_16_MB] = {1};
请注意,如果您指定
0
,编译器可能只会将其存储在 .bss
部分中,即,它仍将在运行时初始化。 它不必这样做,但不这样做就太愚蠢了。 所以现在你的数组被扔进了 .data
段。
当然,这将使生成的可执行文件变得更大(确切地说大约16MB),但内存不会在运行时初始化。 所以问题归结为什么对你来说最重要;将内存归零所需的时间,或最终的可执行文件大小?