C/C++程序内存中变量存储区域的温习
一、了解内存中的分区
c语言在内存中分为下列几个区
- 内存栈区: 存放局部变量名;
- 内存堆区: 存放new或者malloc出来的对象;
- 常数区: 存放局部变量或者全局变量的值;
- 静态区: 用于存放全局变量或者静态变量;
- 代码区:二进制代码。
接下来我们用c语言来查看地址的变化
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void before()
{
}
char g_buf[16];
char g_buf2[16];
char g_buf3[16];
char g_buf4[16];
char g_i_buf[]="123";
char g_i_buf2[]="123";
char g_i_buf3[]="123";
void after()
{
}
int main(int argc, char **argv)
{
char l_buf[16];
char l_buf2[16];
char l_buf3[16];
static char s_buf[16];
static char s_buf2[16];
static char s_buf3[16];
char *p_buf;
char *p_buf2;
char *p_buf3;
p_buf = (char *)malloc(sizeof(char) * 16);
p_buf2 = (char *)malloc(sizeof(char) * 16);
p_buf3 = (char *)malloc(sizeof(char) * 16);
printf("g_buf: 0x%x\n", g_buf);
printf("g_buf2: 0x%x\n", g_buf2);
printf("g_buf3: 0x%x\n", g_buf3);
printf("g_buf4: 0x%x\n", g_buf4);
printf("g_i_buf: 0x%x\n", g_i_buf);
printf("g_i_buf2: 0x%x\n", g_i_buf2);
printf("g_i_buf3: 0x%x\n", g_i_buf3);
printf("l_buf: 0x%x\n", l_buf);
printf("l_buf2: 0x%x\n", l_buf2);
printf("l_buf3: 0x%x\n", l_buf3);
printf("s_buf: 0x%x\n", s_buf);
printf("s_buf2: 0x%x\n", s_buf2);
printf("s_buf3: 0x%x\n", s_buf3);
printf("p_buf: 0x%x\n", p_buf);
printf("p_buf2: 0x%x\n", p_buf2);
printf("p_buf3: 0x%x\n", p_buf3);
printf("before: 0x%x\n", before);
printf("after: 0x%x\n", after);
printf("main: 0x%x\n", main);
if (argc > 1)
{
strcpy(l_buf, argv[1]);
}
return 0;
}
结果如下:
g_buf: 0x80499c8
g_buf2: 0x80499a8
g_buf3: 0x80499d8
g_buf4: 0x80499b8
g_i_buf: 0x8049964
g_i_buf2: 0x8049968
g_i_buf3: 0x804996c
l_buf: 0xbffff6f8
l_buf2: 0xbffff6e8
l_buf3: 0xbffff6d8
s_buf: 0x8049998
s_buf2: 0x8049988
s_buf3: 0x8049978
p_buf: 0x804a008
p_buf2: 0x804a020
p_buf3: 0x804a038
before: 0x8048424
after: 0x8048429
main: 0x804842e
可以看出从低地址到高地址:
函数地址向上增长;全局常量地址向上增长;静态变量地址向下增长;全局变量不变;堆地址向上增长;栈地址向下增长。
二、内存变量存储区域的深入理解
1、栈区(stack):由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2、堆区(heap):一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
3、全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。
程序结束后由系统释放
4、文字常量区 —常量字符串就是放在这里。
5、程序代码区—存放函数体的二进制代码。
三、分区的各自特点
栈
通常是用于那些在编译期间就能确定存储大小的变量的存储区,用于在函数作用域内创建,在离开作用域后自动销毁的变量的存储区。通常是局部变量,函数参数等的存储区。他的存储空间是连续的,两个紧密挨着定义的局部变量,他们的存储空间也是紧挨着的。栈的大小是有限的,通常Visual C++编译器的默认栈的大小为1MB,所以不要定义int a[1000000]这样的超大数组。
堆
通常是用于那些在编译期间不能确定存储大小的变量的存储区,它的存储空间是不连续的,一般由malloc(或new)函数来分配内存块,并且需要用free(delete)函数释放内存。如果程序员没有释放掉,那么就会出现常说的内存泄漏问题。需要注意的是,两个紧挨着定义的指针变量,所指向的malloc出来的两块内存并不一定的是紧挨着的,所以会产生内存碎片。另外需要注意的一点是,堆的大小几乎不受限制,理论上每个程序最大可达4GB。
全局/静态存储区
和“栈”一样,通常是用于那些在编译期间就能确定存储大小的变量的存储区,但它用于的是在整个程序运行期间都可见的全局变量和静态变量。
常量存储区
和“全局/静态存储区”一样,通常是用于那些在编译期间就能确定存储大小的常量的存储区,并且在程序运行期间,存储区内的常量是全局可见的。这是一块比较特殊的存储去,他们里面存放的是常量,不允许被修改。
四、总结
C/C++程序内存中变量存储区域的了解是必要的,但每个区域的应用是需要深究的,想要完全理解需要花费精力。
参考博客:
https://blog.csdn.net/feier7501/article/details/8564300
https://blog.csdn.net/jirryzhang/article/details/79518408