C程序内存布局
1、C程序内存布局图
注意:
- 这个4GB大小的内存(0x0000 0000~0xFFFF FFFF)不是系统的内存,而是进程的
虚拟地址空间
。 - 当一个程序被编译后,只有文本段和数据段。
- 程序被编译后的可执行程序放在硬盘里,叫程序。
- 程序运行后叫进程。
2、虚拟地址空间
- 当创建一个进程时,操作系统会为该进程分配一个
4GB的虚拟地址空间
。(以32 位的操作系统
为例,一个指针长度是 4 字节,4字节指针的寻址能力是从(0x0000 0000~0xFFFF FFFF)。 - 每个进程都会有一个自己的 4GB 虚拟地址空间。这 4GB 的地址空间是“虚拟”的,并不是真实存在的。
3、内存分类
文本段(代码段)
- 编译出来的可执行文件的二进制代码。
- 用来存放代码,如printf,+,=,等代码。
数据段
1)rodata段(文字常量区)
定义:
- rodata段(文字常量区):只读数据段
例:
int main()
{
char *str = "hello";
*(str+1) = 'a'; //str[1] = 'a';
}
结果:segmentation fault; //报段错误
解析:
因为“hello”是常量,存放在.rodata段
,不可改变。
注意:
- str在执行时才有内存,因为它在栈区。
2)data段
定义:
- 存放已经初始化的全局变量或static(静态)变量
- 只要程序运行,所有
.data区
的数据都会一直存在,直到程序终止。
例:
想知道一段程序运行的多少次一下代码可行吗?
func()
{
int total = 0;
total++;
}
结果:不可行
解析:
- 因为total在栈区,每次调用都会重新分配一段内存空间,total的值就会不一样。
正确的方法:
func()
{
static int total = 0;
total++;
}
解析:
- 因为static是静态变量,静态变量放在
.data区
,total的值不会改变。
3)bss段
定义:
- 存放未初始化的全局变量或初始化为0的全局变量或static变量。
- 默认值为0。
栈区
定义:
- 栈区存放局部变量。
- 堆区的空间是
由下往上增长
的。 - 自动分配内存,{}内有效,离开{}自动释放。
- 未初始化的值为随机值。
- 未初始化的静态局部变量,其
值为0
。
堆区
- malloc分配的内存,自己管理,用完要free,否则内存泄漏。
- 堆区的空间足由下往上增长的。
- 内存里面的内容为随机值,一般用memset()清0。
- malloc()动态类型分配内存,在内存中分配一段内存使用。
例:
#include <stdio.h>
#include<stdlib.h>
int main()
{
char *ptr;
ptr = malloc(10); //分配10个字节内存空间
memset(ptr, 0, 10); //memset()清0
realloc(ptr 100);
free(ptr);
p = NULL;
}
free(p)
,是放弃了指针对这个内存的占用,放弃之后,内存的值会改写成随机值。但是指针本身并没有被删除!指针仍然指向原来的那块内存!
因此在free掉指针后,还要把指针指向null,即p = NULL
。
命令行参数区
定义:
- 命令行传递的参数:Is -l /home
int main(int argc, char **argv) - 参数区放命令行传给main()函数的参数:argc,argv。
系统空间
定义:
- 每个程序都有4GB的虚拟内存空间(32位的操作系统)
总结
- 参数区,堆区,栈区,数据段是用来
存放数据
的。
4、局部变量和全局变量
局部变量
定义:
- 花括号内所以定义的变量是局部变量,只能在本花括号使用。
例:
int main(void)
{
int stack_var;
const int rodata_var = 50;
static int s_var;
char *ptr = "hello world";
char arr[] = "hello";
}
未定义的局部变量,其值是随机值
。
未初始化的静态局部变量,其值为0
。
全局变量
定义:
- 在花括号外定义的变量,是全局变量。
例:
#include <stdio.h>
int g_data_var = 20;
int g_bss_var;
static int s_bss_var;
- 已初始化的全局变量,可以被
所有其他c文件或本C文件中的函数调用
,如果另一个c文件想调用全局变量,要用extern声明
。
例:
extern int g_data_var;
-
未初始化的全局变量,其
值为0
,可以被所有其他c文件或本C文件中的函数调用
。 -
未初始化的静态全局变量,其
值为0
,static关键字声明的函数或变量,只能被本C文件调用
。