C语言 内存布局
GCC编译
预处理->编译->汇编->链接
预处理:头⽂件包含、宏替换、条件编译、删除注释...
编译:主要进⾏词法、语法、语义分析等,检查⽆误后将预处理好的⽂件编译成汇编⽂件...
汇编:将汇编⽂件转换成 ⼆进制⽬标⽂件...
链接:将项⽬中的各个⼆进制⽂件+所需的库+启动代码链接成可执⾏⽂件...
内存布局
当我们运行程序时,可加载到 RAM 中。如下是一个内存布局图。
示例代码
#include <stdio.h> #include <stdlib.h> #include "utils.h" /* memory layout test */ /* #define STR(s) #s */ static int u_s_g_var_a; /* 未初始化静态全局变量a 存放在bss段 */ static int i_s_g_var_b = 10; /* 已初始化静态全局变量b 存在在data段 */ static int *u_s_g_var_p; static int *i_s_g_val_p = &u_s_g_var_a; int u_g_var_c; /* 未初始化全局变量c */ int i_g_var_d = 10; /* 已初始化全局变量d */ const int u_g_c_var_e; /* const 修饰未初始化全局常量 */ const int i_g_c_var_f = 10; /* const 修饰初始化全局常量 */ void func_test(void) { printf("func\n"); } int test_memory_layout(void) { int l_var_a; int l_var_b = 10; int *l_var_c = NULL; int *l_var_d = NULL; static int u_s_l_var_e; static int i_s_l_var_f = 10; const int u_l_c_var_g; const int i_l_c_var_h = 10; char *l_var_s = "Hello World"; char l_var_arr[] = "Hello World"; const int *l_p_a = &l_var_a; /* 常量指针 */ int * const l_p_b = &l_var_b; /* 指针常量 */ const int * const l_p_c = &i_l_c_var_h; /* 指向常量的常指针 */ int *l_var_aa = (int *)alloca(sizeof(int) * 4); /* 从栈分配内存 */ static int *i_s_l_var_p = &u_g_var_c; printf("-----------------------------------------------------\n"); printf("栈区\n"); printf("%s\t\t%p\n", STR(l_var_aa), l_var_aa); printf("%s\t\t\t%p\n", STR(l_var_a), &l_var_a); printf("%s\t\t\t%p\n", STR(l_var_b), &l_var_b); printf("%s\t\t%p\n", STR(&l_var_c), &l_var_c); printf("%s\t\t%p\n", STR(&l_var_d), &l_var_d); printf("%s\t\t%p\n", STR(u_l_c_var_g), &u_l_c_var_g); printf("%s\t\t%p\n", STR(i_l_c_var_h), &i_l_c_var_h); printf("%s\t\t%p\n", STR(&l_var_s), &l_var_s); printf("%s\t\t\t%p\n", STR(&l_p_a), &l_p_a); printf("%s\t\t\t%p\n", STR(&l_p_b), &l_p_b); printf("%s\t\t\t%p\n", STR(&l_p_c), &l_p_c); printf("%s\t\t%p\n", STR(l_var_arr), l_var_arr); l_var_c = (int *)malloc(sizeof(int) * 4); l_var_d = (int *)malloc(sizeof(int) * 4); printf("-----------------------------------------------------\n"); printf("堆区\n"); printf("%s\t\t\t%p\n", STR(l_var_c), l_var_c); printf("%s\t\t\t%p\n", STR(l_var_d), l_var_d); printf("-----------------------------------------------------\n"); printf("bss区\n"); printf("%s\t\t%p\n", STR(u_s_g_var_a), &u_s_g_var_a); printf("%s\t\t%p\n", STR(u_g_var_c), &u_g_var_c); printf("%s\t\t%p\n", STR(u_s_l_var_e), &u_s_l_var_e); printf("%s\t\t%p\n", STR(u_g_c_var_e), &u_g_c_var_e); printf("%s\t\t%p\n", STR(&i_s_l_var_p), &i_s_l_var_p); printf("%s\t\t%p\n", STR(&u_s_g_var_p), &u_s_g_var_p); printf("%s\t\t%p\n", STR(&i_s_g_val_p), &i_s_g_val_p); printf("-----------------------------------------------------\n"); printf("data区\n"); printf("%s\t\t%p\n", STR(i_s_g_var_b), &i_s_g_var_b); printf("%s\t\t%p\n", STR(i_g_var_d), &i_g_var_d); printf("%s\t\t%p\n", STR(i_s_l_var_f), &i_s_l_var_f); printf("-----------------------------------------------------\n"); printf("text区\n"); printf("常量\n"); printf("%s\t\t%p\n", STR(i_g_c_var_f), &i_g_c_var_f); printf("%s\t\t\t%p\n", STR(l_var_s), l_var_s); printf("代码\n"); printf("%s\t%p\n", STR(memory_layout_test), memory_layout_test); printf("%s\t\t%p\n", STR(func_test), func_test); free(l_var_c); l_var_c = NULL; free(l_var_d); l_var_d = NULL; return 0; } void main_test(void) { printf("TEST ENTRY\n"); printf("GNU libc version: %s\n", gnu_get_libc_version()); memory_layout_test(); }
运行结果:
----------------------------------------------------- 栈区 l_var_aa 0xffcc5760 l_var_a 0xffcc5784 l_var_b 0xffcc5788 &l_var_c 0xffcc578c &l_var_d 0xffcc5790 u_l_c_var_g 0xffcc5794 i_l_c_var_h 0xffcc5798 &l_var_s 0xffcc579c &l_p_a 0xffcc57a0 &l_p_b 0xffcc57a4 &l_p_c 0xffcc57a8 l_var_arr 0xffcc57b0 ----------------------------------------------------- 堆区 l_var_c 0x57f895b0 l_var_d 0x57f895d0 ----------------------------------------------------- bss区 u_s_g_var_a 0x565d0050 u_g_var_c 0x565d004c u_s_l_var_e 0x565d0058 u_g_c_var_e 0x565cca08 i_s_l_var_p 0x565d004c &i_s_l_var_p 0x565d001c &u_s_g_var_p 0x565d0054 &i_s_g_val_p 0x565d0018 ----------------------------------------------------- data区 i_s_g_var_b 0x565d000c i_g_var_d 0x565d0010 i_s_l_var_f 0x565d0014 ----------------------------------------------------- text区 常量 i_g_c_var_f 0x565cca0c l_var_s 0x565cca15 代码 test_memory_layout 0x565c9b5e func_test 0x565c9b33
参考链接:
https://en.wikipedia.org/wiki/Data_segment
https://en.wikipedia.org/wiki/Memory_segmentation
https://medium.com/@vikasv210/memory-layout-in-c-fe4dffdaeed6
https://github.com/gatieme/AderXCoding/tree/master/language/c/memory_layout
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY