OnTheSSH使用技巧(四)直接观看进程内存
堆(heap)和栈(stack)是进程中的两片内存区域,这是学习编程过程中,特别是C语言这种直接操作内存的程序员必须要掌握的知识。如果能直观的看到进程运行时堆内存和栈内存的变化,相信对内存知识的掌握和程序的调试都能带来帮助。
OnTheSSH是一款SSH工具,提供了图形化的进程内存的监控功能,今天我们就使用它来分析栈和堆内存。
1、先分析栈内存
在linux中,栈内存大小一般限制在8M,可以用 ulimit -a 命令查看系统对栈内存的限制:
编写一段C程序来测试栈内存的申请:
// test1.c #include <stdio.h> main() { // 4M栈内存 char cache[1024 * 1024 * 4]; printf("%X", &cache); //这里scanf()用来阻止程序退出 int a = 0; scanf("%d", &a); }
cache变量是char类型数组,长度定义为4M(1024 * 1024 * 4),然后编译、运行:
程序打印出cache变量的地址: FFA15EA0,先记录在这里,一会儿和进程内存栈地址进行比较。
打开 OnTheSSH 软件的进程监控功能,在进程列表中找到a.out进程,然后点击顶部的“进程内存”按钮:
在进程内存窗口中(下图),显示了a.out进程(进程id 18622)的内存实时状态,上半部分是内存页角度的状态,下半部分是进程在内存中的布局和映射。
内存映射图中显示,a.out进程的栈内存段大小是4M,和cache变量大小相符,地址范围7fffffa15000-7fffffe17000,程序打印的cache地址是FFA15EA0,去除地址前缀,cache地址正好落在栈地址范围内:
2、接下来分析堆内存
C语言中堆内存要用malloc来申请,在64位系统中几乎可以申请到你想得到的任意内存大小(上限极大),比如下面的代码:
//test2.c #include <stdio.h> #include <malloc.h> #include <string.h> main() { int len = 1024 * 1024 * 1024; //申请1G堆内存 int *p = (int*)malloc(len); printf("%X", p); int a = 0; scanf("%d", &a); }
通过malloc申请了1G内存,然后编译、运行:
再次查看OnTheSSH的内存映射:
比对内存地址,malloc申请到的内存地址正落在这段范围:
内存映射也“真实”反应申请到了1G内存,但情况确实如此吗,不尽然!我们用 OnTheSSH 的系统监控功能查看一下内存在系统层面的使用情况:
可以看到系统层面只使用了0.51G内存,肯定没有计算a.out进程的内存啊!怎么回事?
其实这里就碰到了Linux中的copy on write机制:进程中申请的内存在没有写入时,它只是声明存在,系统并不分配物理内存,直到这片内存被写入时才真正分配。
继续测试,修改代码,对malloc申请的堆内存进行写入操作:
//test3.c #include <stdio.h> #include <malloc.h> #include <string.h> main() { int len = 1024 * 1024 * 1024; //申请1G堆内存 int *p = (int*)malloc(len); //写内存 memset(p, 0, len); int a = 0; scanf("%d", &a); }
编译运行,再看系统内存监控,可以看到这时内存才真的被使用:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构