Linux 上 C 程序的内存布局

当密切研究此题目之前,我觉着 C
程序在内存中特发代码段,堆和栈三组成部分重组。前几乎龙面试被问到了这问题,才发现自己的印象是未净的。

每当本文中经解析析一个 C 程序中变量和函数的地点来分析 C
程序在内存中之布局。

先是简单介绍一下Linux上C程序的内存分布。

图片 1

貌似情形下起没有地址及大地址分布着:

  • 程序代码段以及仅读数据段
    • 程序代码,以及字符串常量等都存储于此
  • 可读而写数据段
    • 全局变量,静态变量存储于此地  
  • 数据堆
    • 次第中动态分配的内存以当时等同块 
  • 共享库
    • 次加载的共享库加载在斯地方
  • 数据栈
    • 一些变量,函数参数,函数返回地址等储存在这边
  • 基本地址
    • 操作系统内核内存空间

C语言代码如下(var_memory.c)

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 #include <sys/types.h>
 5 #include <unistd.h>
 6 #include <errno.h>
 7 #include <argp.h>
 8 
 9 int global = 123;
10 static int static_global = 123;
11 
12 int main()
13 {
14     char *string_literal = "hello";
15     static int static_local = 456;
16     char local_array[100] = {'a', 'b', 'c'};
17     int *malloced = (int *)malloc(10*sizeof(int));
18 
19     pid_t pid = getpid();
20     printf("pid: %ld\n", (long)pid);
21 
22     // string_literaling literal and function in this module are loaded
23     // into readonly and excutable segment
24     printf("%.8p: addr of main\n", &main);
25     printf("%.8p: addr of local string_literal literal\n", string_literal);
26     puts("");
27 
28     // static and global variables are allocated in data segment
29     printf("%.8p: addr of global int\n", &global);
30     printf("%.8p: addr of global static int\n", &static_global);
31     printf("%.8p: addr of local static int\n", &static_local);
32     puts("");
33 
34     // allocated in heap
35     printf("%.8p: addr of local malloc\n", malloced);
36     puts("");
37 
38     // errno is from a library
39     printf("%.8p: addr of errno\n", &errno);
40     puts("");
41 
42     // printf is from a library
43     printf("%.8p: addr of printf\n", &printf);
44     puts("");
45 
46     printf("%.8p: addr of  argp_program_verstatic_localon_hook\n", & argp_program_version_hook);
47     puts("");
48 
49     // local variable in stack
50     printf("%.8p: addr of local pid\n", &pid);
51     printf("%.8p: addr of local array\n", local_array);
52     puts("");
53 
54     scanf("%s", local_array);
55     return 0;
56 }

在linux命令行 

make var_memory.c

生成var_memory可执行文件,运行

./var_memory

出口如下:

 1 pid: 4760
 2 0x004b26dd: addr of main
 3 0x004b29d0: addr of local string_literal literal
 4 
 5 0x004b4008: addr of global int
 6 0x004b400c: addr of global static int
 7 0x004b4010: addr of local static int
 8 
 9 0x00d30160: addr of local malloc
10 
11 0xb7db86b4: addr of errno
12 
13 0xb7e0b1c0: addr of printf
14 
15 0xb7f8f798: addr of  argp_program_verstatic_localon_hook
16 
17 0xbf85518c: addr of local pid
18 0xbf855198: addr of local array

开拓另外一个极窗口,根据地方输出的pid,运行命令

 pmap 4760 # 进程id以上面输出为准

 输出如下

 1 4760:   ./var_memory
 2 004b2000      4K r-x-- var_memory
 3 004b3000      4K r---- var_memory
 4 004b4000      4K rw--- var_memory
 5 00d30000    136K rw---   [ anon ]
 6 b7db8000      8K rw---   [ anon ]
 7 b7dba000   1852K r-x-- libc-2.26.so
 8 b7f89000      4K ----- libc-2.26.so
 9 b7f8a000      8K r---- libc-2.26.so
10 b7f8c000      4K rw--- libc-2.26.so
11 b7f8d000     12K rw---   [ anon ]
12 b7fbb000      8K rw---   [ anon ]
13 b7fbd000     12K r----   [ anon ]
14 b7fc0000      8K r-x--   [ anon ]
15 b7fc2000    148K r-x-- ld-2.26.so
16 b7fe7000      4K r---- ld-2.26.so
17 b7fe8000      4K rw--- ld-2.26.so
18 bf836000    132K rw---   [ stack ]
19  total     2352K

自打运行C语言程序与pmap的出口可以看看。

  • main函数(0x004b26dd)和字符串常量(0x004b29d0)被分配在了内存区域
    • 004b2000      4K r-x– var_memory,其中rx代表就读与可实施
  • 全局变量global(0x004b4008),全局静态变量
    static_global(0x004b400c),局部静态变量(0x004b4010)被分配在了数据段

    • 004b4000      4K rw— var_memory,其中rw代表可以读与描写
  • 运用malloc分配的半空中(0x00d30160)处在积聚(heap)里
    • 00d30000    136K rw—   [ anon ]
  • 共享库提供的全局变量errno(0xb7db86b4),被分配在并享库数据段里
    • b7db8000      8K rw—   [ anon ]
  • 共享库提供的函数printf(0xb7e0b1c0),被分配在齐享库代码段里
    • b7dba000   1852K r-x– libc-2.26.so
  • 一对变量(0xbf85518c,0xbf855198)被分配在了栈上
  • bf836000    132K rw—   [ stack ]

欲就首文章,对同一困惑于C程序在内存中布局之而富有帮助。