零初始化结构不会出现在内存中

时间:2018-03-27 03:48:44

标签: c gcc assembly ld osdev

我正在学习汇编,令我惊讶的是,零初始化的结构不会占用内存。 我的代码就是这样。

// in file a.cpp
#include <stdint.h>
struct Bar {
    char filename[8];
    // ignore members here
    uint32_t filesize;
}__attribute__((packed));

typedef struct FAT_ITEM FAT_ITEM;

Bar bar1 = {
    "null",0
};
Bar bar2 = {
    "",0
};

然后我编译代码

gcc -march=i386 -m16 -mpreferred-stack-boundary=2 -ffreestanding -O0 a.cpp a.o
ld -melf_i386 -N --oformat binary -o a.bin a.o

但是,当我使用dd读取a.bin中的二进制文件时,我看到了

00000000: 6e75 6c6c 0000 0000 0000 0000            null........
(END)

bar2未出现在内存中。 32位零来自bar1.filesize。然后(END)跟随。

我正在学习16位x86汇编,所以编译选项可能很奇怪。但我认为它们不会导致这个问题。

任何人都可以帮助我并解释为什么bar2被“忽略”了吗?

1 个答案:

答案 0 :(得分:4)

在BSS中放置零内容的编译器,which the default linker script doesn't allocate space for in a flat binary;它在其他部分结束后开始。

在C代码运行之前在启动时自行归零,或者禁止编译器使用BSS(例如-fno-zero-initialized-in-bss

您可以查看gcc -S输出;注意.lcomm or .comm directives为所有零init静态/全局变量保留BSS空间。在编译普通的Linux可执行文件时,您不希望在可执行文件中明确存储大量的零。

有关讨论,请参阅https://gcc.gnu.org/ml/gcc-help/2007-07/msg00097.html,例如如果你不想写一个在启动时运行的零init循环,你可以使用__attribute__将一个实际需要零的数组放入另一个部分。然后你可以让一些不需要在BSS中完全初始化的数组,但是在你的二进制文件中占用空间以便在需要它的其他东西上显式为零。