程序的组成部分
![程序组成部分](https://imgconvert.csdnimg.cn/aHR0cDovL2ltZy5ibG9nLmNzZG4ubmV0LzIwMTYwMjEzMDkzMjU5NzUw?x-oss-process=image/format,png)
如上图所示。程序由 code 到 stack 地址由小到大,
.text` 之前有一段不可读的区域;
.text + .rodata + .data + .bss + .heap + .stack 的大小是在程序编译阶段确定的;
-
text 段:存放程序代码的区域;
-
.rodata 段:ro 表示 read only ,rodata 表示只读常数据段;
-
常量不一定存放再 .rodata 处,也有可能存放再 .text例如一些立即数;
-
字符串常量存放在 .text 段,在编译期间就可以确定;
-
const 修饰的变量存放在 .text 段,在程序运行期间确定
-
.data
段:存储已初始化的全局变量;已初始化的全局变量在文件和运行中都占存储空间;
-
.bss 段:存放未初始化的全局变量或者全局变量初始化为 0;
-
heap 段:堆区,用于动态申请内存的区域,由程序员申请内存和释放内存;
-
.stack 段:栈区,存放局部变量和函数参数,由系统申请内存和释放内存;
-
Stack
之后是不可访问的系统代码区;
示例说明 .data
和 .bss
段
.data
段的变量既占文件空间,又占运行空间
// 文件名: data.c
int data_arr[1024 * 1024] = {1, }; // .data 段,初始化为 1,空间大小为 4M;
int main(int argc, char *argv[])
{
return 0
}
$ gcc -g data.c -o data
$ ls -l data
-rwxrwxr-x 1 zach zach 4203984 9月 6 08:27 data
objdump -h data | grep \\.data
24 .data 00400020 0000000000601020 0000000000601020 00001020 2**5
由上述可知文件空间和运行空间,都有 4M 多;
.bss
段的变量不占文件空间,但是占用运行空间;
// 文件名: bss.c
int data_arr[1024 * 1024] = {0, }; // .bss 段,初始化为 0,空间大小为 4M;
int main(int argc, char *argv[])
{
return 0;
}
$ gcc -g exercise.c -o bss
$ ls -l bss
-rwxrwxr-x 1 zach zach 9664 9月 6 08:31 bss
$ objdump -h bss | grep \\.bss
25 .bss 00400020 0000000000601040 0000000000601040 00001030 2**5
由上述可知,.bss
段不占文件空间,占用运行空间;
代码说明
int data_arr2[1024 * 1024] = {1, }; // .data 段
int data_arr1[1024 * 1024] = {0, }; // .bss 段
char * p1; // .bss段
int main()
{
int b; // 栈区 .stack
char s[] = "abs"; // 栈区 .stack
char *p2; // 栈区 .stack
char *p3 = "12345"; // “12354\0”在只读常量区 .rodata,p3在栈区
static int c = 0; / / 全局静态区,.bss段
p1 = (char *)malloc(10);// 在堆区分配10个Byte
p2 = (char *)malloc(20);// 在堆区分配20个Byte
strcpy(p1,"123456"); // “123456\0”在常量区,常量区应该介于code和Data之间
}
内存的分配方式
主要由三种分配方式:
-
在静态存储区分配:
-
在栈上分配:
-
局部变量;
-
函数的形参;
-
在函数退出时,自动清空;
-
在堆上分配:动态内存分配:
-
molloc 申请内存;
-
realloc 再分配;
-
free 释放内存;