如何编译这个程序填满我的电脑?

时间:2017-11-24 15:16:37

标签: c gcc

int main[-1U] = {1};

这很简单。用

编译
gcc foo.c

当我在后台lsof挂起GCC时,至少我无法使用gcc & :找到该文件,但二级存储空间<16> (硬盘)将被吃掉。

这是如何运作的?

4 个答案:

答案 0 :(得分:7)

您可以使用简单的printf

来解决这个谜团
printf("%zu\n", (size_t)-1U);

这会产生4294967295demo) - 足以在sizeof(int)等于4的系统上填充16Gb的内存。

要了解为什么在文件系统中占用这么多空间,请将foo编译为目标文件,然后运行size实用程序。

我修改了程序,将数组大小调整为1,000,000个元素。以下是您运行size时获得的输出:

$ gcc -c foo.c
$ size -A -d foo.o
foo.o  :
section        size   addr
__text            0      0
__data      4000000      0
Total       4000000

__data段包含初始化数据。编译器填写它,因为您提供了{1}初始化程序。如果省略它,磁盘上可执行文件的大小将缩小到几千字节,因为该数组将放入未初始化的段:

$ size -A -d foo.o
foo.o  :
section     size   addr
__text         0      0
Total          0

答案 1 :(得分:4)

无符号算术的模数比给定类型的最大值多一个。

因此-1U-1 + MAX_UINT + 1,在2^32-1的架构上为unsigned == uint32_t。如果你的sizeof(int) == 4int x[-1U] = {1};将需要4*(2^32-1) B =~ 16 GiB存储,并且存储不会被删除,因为它不是全零。

您的xmain的事实不起作用(除了它是main将允许链接器完成链接,即使这将导致损坏的可执行文件你的main不是函数。)

int x[-1U] = {1};
int main(){}

也需要超过16GiB,这个例子应该被完美定义(只要你的实现可以处理一个大的数组),不像你的例子main有一个它不应该有的类型。

答案 2 :(得分:1)

未初始化的静态分配数组通常会转到.bss部分。它们被隐式初始化为零。这些数据不需要存储在二进制文件中,因为启动代码“知道”它应该在运行时将此部分初始化为全零。所以我们可以说未初始化的数组,即使静态分配也不会消耗二进制大小。

另一方面,初始化的数据(非零初始化),如您所示,将转到.data部分。哪个是生成的二进制文件的一部分,因为初始化数据必须存储在某处。在您的情况下,您有sizeof(int) * UINT_MAX-1U = UINT_MAX)初始化数据(可能等于16Gb),这些数据都会添加到生成的二进制文件中。

答案 3 :(得分:0)

也许,您的系统上启用了虚拟内存。因此,当您尝试在内存中分配16 GB的数据时,由于虚拟内存,硬盘上会出现这么大的文件。

16 GB,因为您要分配4294967295个大小为4的整数。