今天,帮人看了一个问题,每次执行到函数 A 中程序就挂了。
我看到代码中函数 A 中定义了一个超大体积的结构体变量,断定是爆栈了。
这里回顾一下作下记录,C/C++程序中变量在内存中的位置:
初始化为非0的静态变量、全局变量在数据段 .data区,编译出的文件需要记录其初始值,所以比较浪费空间。这里所说的浪费空间指的是编译链接之后的文件比较小,是在程序没加载进内存之前的一个静态的大小,毕竟一旦程序运行,对于32bit程序,每个进程可寻址的地址空间都为 2^32 == 4G.
字符串字面量“hello world” 在只读数据段 .rodata.
初始化非0 和 未初始化的静态变量和全局变量在 .bss 段(better for save space),编译出的文件中值包含符号,节省空间。
增加大体积全局变量(这里不初始化 === 初始化为 0),编译出的 exe 为106KB,基本无变化。
另外栈和堆就不说。const 常量通常是编译器开洞,做一些常量折叠的手脚而已。char *p = "hello world". "hello world"才是真实的存储于 .rodata 只读的。
我看到代码中函数 A 中定义了一个超大体积的结构体变量,断定是爆栈了。
这里回顾一下作下记录,C/C++程序中变量在内存中的位置:
初始化为非0的静态变量、全局变量在数据段 .data区,编译出的文件需要记录其初始值,所以比较浪费空间。这里所说的浪费空间指的是编译链接之后的文件比较小,是在程序没加载进内存之前的一个静态的大小,毕竟一旦程序运行,对于32bit程序,每个进程可寻址的地址空间都为 2^32 == 4G.
字符串字面量“hello world” 在只读数据段 .rodata.
初始化非0 和 未初始化的静态变量和全局变量在 .bss 段(better for save space),编译出的文件中值包含符号,节省空间。
简单的实验:
int main(int argc, char *argv[])
{
return 0;
}
这只是主题代码,其他的忽略,debug 版本编译出的 exe 为 104KB.
int g_arr[1000000] = {0};
int main(int argc, char *argv[])
{
return 0;
}
增加大体积全局变量(这里不初始化 === 初始化为 0),编译出的 exe 为106KB,基本无变化。
int g_arr[1000000] = {1};
初始化为非 0 值,编译出的 exe 为 4012KB .全局数组的大小为:1000000 * 4 / 1024 = 3906.25KB ,可以看到 exe 增加的体积毕本就是该全局变量的体积。
定义静态类型。
int main(int argc, char *argv[])
{
static int g_arr[1000000];
return 0;
}
编译出的 exe 的大小为104KB,同样的,在exe 加载到内存里运行时,静态数组在自动被初始为0.
int main(int argc, char *argv[])
{
static int g_arr[1000000] = {1};
return 0;
}
初始化一下,编译出的 exe 的体积立马变大为4010KB,比定义为全局变量的稍微小一点点。
另外栈和堆就不说。const 常量通常是编译器开洞,做一些常量折叠的手脚而已。char *p = "hello world". "hello world"才是真实的存储于 .rodata 只读的。