【操作系统】Linux中C程序的内存分布情况

Linux将运行着的C程序分成不同的段,有些段的大小是固定的,有些是可变动的。

1. STACK

在HEAP之上,唯一一个由高地址向低地址增长的段。存放函数中的局部变量、临时变量、函数参数、返回地址、寄存器值等(文字常量静态变量除外)。所有申请和销毁的操作由编译器负责。

2. HEAP

在BSS之上,向高地址增长,通过malloc/free等申请/销毁。内部实现时所有空闲空间由链表串联起来,频繁的申请和销毁容易形成碎片。所有申请和销毁的操作由应用程序负责。

3. BSS(Blocked Started by Symbol)

存放未初始化的全局变量static变量,整个区段在程序启动时被初始化为0。

4. DATA

存放已初始化的全局变量和static变量文字常量全局常量。数据段所包含的数据的生命周期持续到程序结束。Linux将数据段分为已初始化的只读数据段(Read-only)和已初始化的读写数据段(Read-write)。

5. CODE/TEXT

代码段存放可执行代码,一般来说大小固定,并且只读。通常处于最底部,即最低地址部分。

 -------------------
|       STACK      |  <-高地址
 -------------------
|        HEAP       |
 -------------------
|         BSS         |
 -------------------
|        DATA        |
 -------------------
|   CODE/TEXT   |  <-低地址
 -------------------

#include <stdio.h>

//
// Name          Size      VMA       LMA       File off  Algn
// .text         0000057c  08048390  08048390  00000390  2**4
//                   CONTENTS, ALLOC, LOAD, READONLY, CODE
// .rodata       000002d2  08048928  08048928  00000928  2**2
//                   CONTENTS, ALLOC, LOAD, READONLY, DATA
// .data         00000020  0804a014  0804a014  00001014  2**2
//                   CONTENTS, ALLOC, LOAD, DATA
// .bss          00000024  0804a034  0804a034  00001034  2**2
//                   ALLOC
//

int g_int_1;
// ADDRESS(g_int_1) = 0x804a044(bss)
int g_int_2 = 10;
// ADDRESS(g_int_2) = 0x804a01c(data)

static int g_static_1;
// ADDRESS(g_static_1) = 0x804a03c(bss)
static int g_static_2 = 10;
// ADDRESS(g_static_2) = 0x804a020(data)

const int g_const_1 = 10;
// ADDRESS(g_const_1) = 0x8048930(read-only data)
/* const int g_const_2; Compile Error: const object must be initialized if not extern*/

char g_ch_array_1[10];
// VALUE(g_ch_array_1) = 0x804a048(bss)
char g_ch_array_2[] = "abc";
// VALUE(g_ch_array_2) = 0x804a024("abc" in data).
// ADDRESS(g_ch_array_2) = 0x804a024(g_ch_array_2 in data).

char *g_p_string_1;
// VALUE(g_p_string_1) = NULL(g_p_string_1 in bss)
char *g_p_string_2 = "abc";
// VALUE(g_p_string_2) = 0x8048934("abc" in read-only data).
// ADDRESS(g_p_string_2) = 0x804a028(g_p_string_2 in data segment).

const char g_c_ch_array_1[] = "abc";
// VALUE(g_c_ch_array_1) = 0x8048938("abc" in read-only data).
// ADDRESS(g_c_ch_array_1) = 0x8048938(g_c_ch_array_1 in read-only data).
char const g_c_ch_array_2[] = "abc";
// VALUE(g_c_ch_array_2) = 0x804893c("abc" in read-only data).
// ADDRESS(g_c_ch_array_2) = 0x804893c(g_c_ch_array_2 in read-only data).

const char *g_c_p_string_1 = "abc";
// VALUE(g_c_p_string_1) = 0x8048934("abc" in read-only data).
// ADDRESS(g_c_p_string_1) = 0x804a02c(g_c_p_string_1 in data segment).
char * const g_c_p_string_2 = "abc";
// VALUE(g_c_p_string_2) = 0x8048934("abc" in read-only data).
// ADDRESS(g_c_p_string_2) = 0x8048940(g_c_p_string_2 in read-only data).

void main()
{
	int l_int_1;
	// ADDRESS(l_int_1) = 0xbf8be29c(stack)
	int l_int_2 = 10;
	// ADDRESS(l_int_2) = 0xbf8be298(stack)

	static int l_static_1;
	// ADDRESS(l_static_1) = 0x804a040(bss)
	static int l_static_2 = 10;
	// ADDRESS(l_static_2) = 0x804a030(data)

	const int l_const_1 = 10;
	// ADDRESS(l_const_1) = 0xbf8be294(stack)

	char l_ch_array_1[10];
	// VALUE(l_ch_array_1) = 0xbf8be2a6(stack)
	char l_ch_array_2[] = "abc";
	// VALUE(l_ch_array_2) = 0xbf8be2b8("abc" in stack).
	// ADDRESS(l_ch_array_2) = 0xbf8be2b8(l_ch_array_2 in stack)

	char *l_p_string_1;
	// VALUE(l_p_string_1) = random(l_p_string_1 in stack)
	char *l_p_string_2 = "abc";
	// VALUE(l_p_string_2) = 0x8048934("abc" in read-only data).
	// ADDRESS(l_p_string_2) = 0xbf8be290(l_p_string_2 in stack)

	const char l_c_ch_array_1[] = "abc";
	// VALUE(l_c_ch_array_1) = 0xbf8be2b4("abc" in stack).
	// ADDRESS(l_c_ch_array_1) = 0xbf8be2b4(l_c_ch_array_1 in stack).
	char const l_c_ch_array_2[] = "abc";
	// VALUE(l_c_ch_array_2) = 0xbf8be2b0("abc" in stack).
	// ADDRESS(l_c_ch_array_2) = 0xbf8be2b0(l_c_ch_array_2 in stack).

	const char *l_c_p_string_1 = "abc";
	// VALUE(l_c_p_string_1) = 0x8048934("abc" in read-only data).
	// ADDRESS(l_c_p_string_1) = 0xbf8be28c(l_c_p_string_1 in stack).
	char * const l_c_p_string_2 = "abc";
	// VALUE(l_c_p_string_2) = 0x8048934("abc" in read-only data).
	// ADDRESS(l_c_p_string_2) = 0xbf8be288(l_c_p_string_2 in stack).
}

  • Note 1:区分字符数组(Char Array)和文字常量(String Literal)。考虑两种情况char s[] = "abc"和char *s = "abc",其中前者"abc"是字符数组,后者"abc"是文字常量。两者的区别是字符数组存放在stack/data segment,其内容可修改。而文字常量存放在read-only data segment,内容不可修改。
  • Note 2:字符数组的地址。字符数组存放的位置与当前作用域相关,如果作用域在全局,则存放在data segment,如果作用域在局部,则存放在stack。定义char s[] = "abc",那么s == &s。
  • Note 3:函数中的常量存放在stack。
  • Note 4:函数中的文字常量存放在read-only data segment。
  • Note 5:函数中的静态变量存放在bss/data segment。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值