关于内存问题
程序1,
#include "stdio.h"
char str[1024][1024] = {0};
int main()
{
return 0;
}
程序2
#include "stdio.h"
char str[1024][1024] = {1};
int main()
{
return 0;
}
为什么程序1生成的1.exe的大小为172KB,而程序2成成的2.exe的大小为1.36M。程序大小怎么差这么多。请高手详细解答一下。
[解决办法]
程序2试图给1M字节的空间赋初值。
[解决办法]
因为程序1中的char str[1024][1024]初始化为0,生成可执行文件后,在文件中并不占空间。
但在程序2中,初始化为1,他会占用文件的磁盘空间。
请参看程序员的自我修养—链接、装载与库一书
[解决办法]
可执行文件的格式是 PE 格式的. PE 是按照区段来组织, 执行的时候这些区段直接映射到内存里面, 由于文件中的区段和内存中的区段对齐方式不一样(文件中的区段大小是 0x200 的整数倍, 内存中的区段大小是 0x1000 的整数倍. 所以从文件映射到内存时多余的空间会用 0 来填充. 对于未初始化或初始化为 0 的变量, 文件中可以不留出大小, 只是指明映射到内存中的大小就好了. 这样文件大小就减小了.
[解决办法]
5楼说得正确。楼主可以参考上面的两个程序生成的汇编代码就清楚了。
对于程序1,编译器会认为变量str[1024][1024]为弱符号。未初始化或初始值为0的全局变量,编译器会认为它是弱符号,为此会把变量放置到BSS section。而当最后生成可执行文件时,linker并不会为BSS section的数据分配文件空间来存放这些数据,而仅仅是有一个BSS section来表明该可执行文件中BSS section的大小。为此,放置到BSS section中的数据,不会增加最后生成的可执行文件的大小。
在VC2008环境下,你会看到编译为变量生成的汇编代码为:
PUBLIC?str@@3PAY0EAA@DA; str
_BSSSEGMENT
?str@@3PAY0EAA@DA DB 0100000H DUP (?); str
_BSSENDS
对于程序2,编译器会认为变量str[1024][1024]为强符号。初始值非0的全局变量为强符号,为此会把变量放置到DATA section。而当最后生成可执行文件时,linker会为DATA section的数据分配文件空间来存放这些数据,即DATA section有多大,那么最后就会占多少可执行文件字节。为此,放置到DATA section中的数据,会增加最后生成的可执行文件的大小。
在VC2008环境下,你会看到编译为变量生成的汇编代码为:
PUBLIC?str@@3PAY0EAA@DA; str
_DATASEGMENT
?str@@3PAY0EAA@DA DB 01H; str
ORG $+1048575
_DATAENDS
上的代码,在DATA segment占据了1048575 + 1 = 0x100000大小的空间