程序是如何运行起来的(MD格式)

程序的组成部分

程序组成部分

如上图所示。程序由 code 到 stack 地址由小到大,

.text 之前有一段不可读的区域;

.text + .rodata + .data + .bss + .heap + .stack的大小是在程序编译阶段确定的;

  • .text 段:存放程序代码的区域;

  • .rodata 段:ro 表示 read only ,rodata 表示只读常数据段;

    • 常量不一定存放再 .rodata 处,也有可能存放再 .text例如一些立即数;
    • 字符串常量存放在 .text段,在编译期间就可以确定;
    • const 修饰的变量存放在 .text 段,在程序运行期间确定
  • .data 段:存储已初始化的全局变量;已初始化的全局变量在文件和运行中都占存储空间;

  • .bss 段:存放未初始化的全局变量或者全局变量初始化为 0;

    • 在文件中不占存储空间;
    • 在运行中占存储空间;
  • heap 段:堆区,用于动态申请内存的区域,由程序员申请内存和释放内存;

    • malloc:用来分配一块制定大小的内存;
    • realloc:用来调整/重分配一块存在的内存;
    • free:用来释放不再使用的内存;
    • 内存泄漏:内存分配了不释放;
    • 程序 crash:释放了不存在的内存;
    • 缓冲区溢出(Buffer Overflow):写或读超过范围的内存;
    • 可以使用 valgrind 程序内存;
  • .stack 段:栈区,存放局部变量和函数参数,由系统申请内存和释放内存;

    • 栈是一种数据结构,栈中数据的存取方式是:先进先出,后进后出;
    • 通常情况下,栈地址向下(低地址)增长,没 Push 一个地址,栈顶就向低地址扩展,每 Pop 一个元素,栈顶就向高地址回退;
  • 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 96 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 96 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之间
}

内存的分配方式

主要由三种分配方式:

  • 在静态存储区分配:
    • 涉及到的变量由:字符串常量、static 申请的变量, 全局变量;
    • 涉及到的内存区段有:.rodata 段、.data 段.bss 段;
    • 静态存储区的变量生命周期是整个程序的运行周期;
  • 在栈上分配:
    • 局部变量;
    • 函数的形参;
    • 在函数退出时,自动清空;
  • 在堆上分配:动态内存分配:
    • molloc 申请内存;
    • realloc 再分配;
    • free 释放内存;
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值