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了,我反复做过几次这个实验验证自己的想法,一开始也因为这个卡了一会儿,不得不说自己做一遍,理解真的会加深很多。
这篇帖子就总结到这里吧,如有不正确的地方还请指出,大家共同进步!
- linux应用编程笔记(3)addr.c分析linux应用程序地址布局
- [3]Linux应用程序地址布局
- [3]Linux应用程序地址布局
- linux应用程序(3)---应用程序地址布局
- Linux应用程序地址布局
- Linux应用程序地址布局
- linux应用程序地址布局
- Linux应用程序地址布局
- Linux应用程序地址布局
- Linux应用程序地址布局
- Linux应用程序地址布局
- 2、Linux应用程序地址布局
- Linux学习之Linux应用程序地址布局
- Linux应用编程- 程序地址布局 动态库 静态库
- Linux应用程序在内存地址布局
- 一步一步学好Linux开发之Linux应用程序地址布局
- 2-4 Linux应用程序地址分析
- Linux C编程笔记
- mysql读写分离(二)-----主从复制
- hdu1203 I NEED A OFFER!(01背包)
- 笔记123--viewpager一页显示多个item
- 异常
- 如何实现上拉加载,默认加载10条数据,上拉再加载10条数据。
- linux应用编程笔记(3)addr.c分析linux应用程序地址布局
- sql server2005分页rownumber()
- MOSFET选型注意事项及应用实例
- 【集训队作业】MONOPLOY
- 搜索的时候,不改变页数。
- 白话经典算法系列之四 直接选择排序及交换二个数据的正确实现
- 让你的Chrome App支持多语言(i18n)
- 交友
- 图解Android View的scrollTo(),scrollBy(),getScrollX(), getScrollY()