linux应用编程笔记(3)addr.c分析linux应用程序地址布局

来源:互联网 发布:对网络语言的看法800字 编辑:程序博客网 时间:2024/06/14 22:12

摘要:通过编写一个例程addr.c,总结分析了linux应用程序的地址布局,包括代码段,数据段,BSS段,堆(heap)和栈(stack)的分布,分析了程序在运行之后,各个变量常量动态申请分配的内存分别在什么位置。


一、程序的构成及内存分布

    linux应用程序的构成包括:代码段,数据段,BSS段(未初始化数据段),堆和栈。

    上面组成部分当程序在linux中运行的时候,分布情况如下:

    从下到上依次是代码段,数据段,BSS段,堆和栈,其中代码段的起始地址固定为0x08048000,栈按照自上向下生长,堆按照自下向上生长。


二、数据存放的位置

    1.代码段:代码,全局常量const,字符串常量。

    2.数据段:全局变量,静态变量。

    3.堆:动态分配的区域

    4.栈:局部变量,局部只读变量

    总之,凡事被static修饰的变量,全部放在数据段,无论是全局变量还是局部变量。

 

三、分析addr.c查看数据存放位置

    这里我写的addr.c函数如下:

<span style="font-size:18px;">#include<stdio.h>#include<malloc.h> int g_a;int g_b=0; static int s_g_a;static int s_g_b=0; const int c_g_b=0;  int main(void){    intl_a;    intl_b=0;       staticint s_l_a;    staticint s_l_b=0;       constint c_l_b=0;       int*m_l_a;    m_l_a=malloc(sizeof(int));          printf("1-g_aaddress is:%0x,g_a is:%d\n",&g_a,g_a);    printf("2-g_baddress is:%0x,g_b is:%d\n",&g_b,g_b);    printf("3-s_g_aaddress is:%0x,s_g_a is:%d\n",&s_g_a,s_g_a);    printf("4-s_g_baddress is:%0x,s_g_b is:%d\n",&s_g_b,s_g_b);    printf("5-c_g_baddress is:%0x,c_g_b is:%d\n",&c_g_b,c_g_b);       printf("6-l_aaddress is:%0x,l_a is:%d\n",&l_a,l_a);    printf("7-l_baddress is:%0x,l_b is:%d\n",&l_b,l_b);    printf("8-s_l_aaddress is:%0x,s_l_a is:%d\n",&s_l_a,s_l_a);          printf("9-s_l_baddress is:%0x,s_l_b is:%d\n",&s_l_b,s_l_b);    printf("10-c_l_baddress is:%0x,c_l_b is:%d\n",&c_l_b,c_l_b);       printf("11-m_l_aaddress is:%0x,m_l_a is:%d\n",m_l_a,*m_l_a);         while(1);     return0;    }</span>

    主要是查看不同的变量,包括全局未初始化,全局初始化,静态全局未初始化,静态全局初始化,局部未初始化,局部初始化,静态局部未初始化,静态局部初始化和动态分配的内存。

    按照下面的指令操作:

    #gcc addr.c –o addr

    #./addr

    运行起来之后,重新打开一个终端,然后:
    # ps aux |grep ./addr

    这时候就找到addr这个进程运行的pid号,我的如下;

   

    这里是12501,然后接着输入:

    # cat /proc/12501/maps

    这时候我要的信息就出来了:

    

    下面我做了一张表格,把这个maps和我们刚才的变量对应起来:

 

名称

地址范围

包含变量

代码段

08048000-08049000

c_g_b

数据段

08049000-0804a000

g_a,g_b,s_g_a,s_g_b,s_l_a,s_l_b

090d4000-b78fe000

m_l_a

bfc8a000-bfcab000

l_a,l_b,c_l_b

BSS段

0804995c-0804997c

g_a,g_b,s_g_a,s_g_b,s_l_a,s_l_b

    这里和我们刚才总结的是一样的吧,最后的BSS段是因为要借助另一个方法来查看,输入:

    # readelf –S addr

    我的出现如下信息:

    可以看到bss的信息了吧,往上面的表里面填,这里给了一个起始地址,一相对数据段起始地址的偏移量和这段的大小,大小为多少呢,20,结束地址我们也可以计算得到,往里面填进去,可以完整的得到上表。

    这里为什么BSS段和数据段包含的变量都重合了呢?难道数据段里面的东西都包含在了BSS段吗?显然不是的!!!因为我的程序即使初始化了,也给的是0,程序默认是没有进行初始化的,我们的BSS段就是数据段里面未初始化的数据存放的地方,不信你可以把g_b初始化的时候改为1,再按照以上方法,BSS段里面就没有g_b了,我反复做过几次这个实验验证自己的想法,一开始也因为这个卡了一会儿,不得不说自己做一遍,理解真的会加深很多。

    这篇帖子就总结到这里吧,如有不正确的地方还请指出,大家共同进步!

0 0
原创粉丝点击