memory check

介绍

关于物理内存的统计信息,可以通过/proc/phymem目录下的文件查看:

说明

/proc/phymem

dist

显示物理内存使用分布信息

mem: 262144 kB
  |--mem_other: 15996 kB
  |--mem_linux: 246148 kB
       |--mem_reserved: 31268 kB
       |--mem_total: 214880 kB
            |--mem_free: 4608 kB
            |--mem_buffer: 0 kB
            |--mem_cache: 82340 kB
            |--mem_user: 90568 kB
            |    |--active(anon): 44140 kB
            |    |--inactive(anon): 46428 kB
            |--mem_kernel: 37364 kB
                 |--kernelStack: 3432 kB
                 |--pageTables: 9224 kB
                 |--slab: 6680 kB
                 |--vmalloc: 28268 kB

说明:

  • mem_other: 与Linux无关的物理内存,在6820中,主要是指ThreadX,NK虚拟机,以及一部分Shared内存。
  • mem_linux: Linux相关的物理内存。
  • mem_reserved: Linux保留内存,包括Kernel的镜像,内存文件系统。
  • mem_total: 可供分配使用的物理内存。
  • mem_free: 空闲的物理内存。
  • mem_buffer:块设备的写缓冲。
  • mem_cache: 文件系统的读缓存。
  • mem_user: 用户态进程分配的物理内存
  • active(anon): active匿名页
  • inactive(anon): inactive匿名页
  • mem_kernel: kernel分配的物理内存
  • kernelStack: kernel的stack占用内存
  • pageTables: 页表消耗内存
  • slab: slab消耗内存
  • vmalloc: vmalloc使用内存

map

显示Os管理的物理内存地址区间

0x00203000 - 0x00340000    1268kB
0x00359000 - 0x00400000    668kB
0x00460000 - 0x00480000    128kB
0x004e0000 - 0x004ff000    124kB
0x011c2000 - 0x10000000    243960kB

pages

根据页面属性统计物理页的使用情况

pages of RAM       61537
free pages         1745
reserved pages     7943
slab pages         2001
pages shared       11642
pages swap cached  0
buddy pages        0
other pages        38206

showmem-trigger

触发show_mem函数,内容输出至kmsg

kmsg中信息显示如下:

[ 1264.184000] Mem-info:
[ 1264.184000] Normal per-cpu:
[ 1264.184000] CPU    0: hi:   90, btch:  15 usd:   3
[ 1264.184000] active_anon:9696 inactive_anon:11544 isolated_anon:0
[ 1264.184000]  active_file:10744 inactive_file:8828 isolated_file:0
[ 1264.184000]  unevictable:364 dirty:0 writeback:0 unstable:0
[ 1264.184000]  free:3382 slab_reclaimable:465 slab_unreclaimable:1324
[ 1264.184000]  mapped:9067 shmem:76 pagetables:2268 bounce:0
[ 1264.184000] Normal free:13528kB min:1976kB low:2468kB high:2964kB active_anon:38784kB inactive_anon:46176kB active_file:42976kB inactive_file:35312kB unevictable:1456kB isolated(anon):0kB isolated(file):0kB present:244116kB mlocked:0kB dirty:0kB writeback:0kB mapped:36268kB shmem:304kB slab_reclaimable:1860kB slab_unreclaimable:5296kB kernel_stack:3416kB pagetables:9072kB unstable:0kB bounce:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[ 1264.185000] lowmem_reserve[]: 0 0 0
[ 1264.185000] Normal: 362*4kB 282*8kB 148*16kB 111*32kB 33*64kB 6*128kB 2*256kB 1*512kB 0*1024kB 0*2048kB 0*4096kB = 13528kB
[ 1264.185000] 20012 total pagecache pages
[ 1264.185000] 0 pages in swap cache
[ 1264.185000] Swap cache stats: add 0, delete 0, find 0/0
[ 1264.185000] Free swap  = 0kB
[ 1264.185000] Total swap = 0kB
[ 1264.188000] 61537 pages of RAM
[ 1264.188000] 3986 free pages
[ 1264.188000] 8082 reserved pages
[ 1264.188000] 1328 slab pages
[ 1264.188000] 110458 pages shared
[ 1264.188000] 0 pages swap cached

应用场景

内核裁剪

当裁剪掉某些功能后,通过/proc/phymem/dist查看内存变化情况。

比如,

定义 CONFIG_KALLSYMS_ALL                             未定义 CONFIG_KALLSYMS_ALL
mem: 262144 kB                                      mem: 262144 kB                              
  |--mem_other: 15996 kB                              |--mem_other: 15996 kB                    
  |--mem_linux: 246148 kB                             |--mem_linux: 246148 kB                   
       |--reserved: 31772 kB                               |--mem_reserved: 31268 kB     --减少      
       |--mem_total: 214376 kB                             |--mem_total: 214880 kB       --增加       
            |--mem_free: 4672 kB                                |--mem_free: 4608 kB            
            |--mem_buffer: 0 kB                                 |--mem_buffer: 0 kB             
            |--mem_cache: 81104 kB                              |--mem_cache: 82340 kB          
            |--mem_user: 87288 kB                               |--mem_user: 90568 kB           
            |    |--active(anon): 45848 kB                      |    |--active(anon): 44140 kB  
            |    |--inactive(anon): 41440 kB                    |    |--inactive(anon): 46428 kB
            |--mem_kernel: 41312 kB                             |--mem_kernel: 37364 kB         
                 |--kernelStack: 3144 kB                             |--kernelStack: 3432 kB    
                 |--pageTables: 8292 kB                              |--pageTables: 9224 kB     
                 |--slab: 9752 kB                                    |--slab: 6680 kB           
                 |--vmalloc: 30268 kB                                |--vmalloc: 28268 kB       

<think>我们正在讨论如何在调试过程中检查内存完整性。用户可能遇到了内存相关的问题(如崩溃、数据损坏等),并希望在调试时验证内存状态。以下是一些关键方法: ### 1. **使用调试器的内置内存检查工具** - **GDB (Linux/Unix)**: ```gdb # 检查堆内存完整性 (需要glibc支持) (gdb) call malloc_stats() # 打印堆统计信息 (gdb) call malloc_consolidate(0) # 强制整理堆碎片 (gdb) call mcheck() # 启用堆一致性检查(需提前在代码中调用mcheck) ``` - 使用`mcheck`需要重新编译代码: ```c #include <mcheck.h> int main() { mcheck(NULL); // 注册内存检查处理函数 // ... 程序代码 ... } ``` ```bash gcc -lmcheck program.c -o program ``` - **WinDBG (Windows)**: ```windbg !heap -s # 显示所有堆的摘要 !heap -stat -h <堆地址> # 查看特定堆的统计 !heap -flt s <大小> # 过滤显示特定大小的堆块 !heap -p -a <地址> # 详细分析指定地址的堆块 ``` ### 2. **启用操作系统级内存保护** - **Linux (通过sysctl)**: ```bash # 启用所有用户空间的内存保护(需要root) sysctl -w kernel.yama.protected_nonaccess_hardlinks=1 sysctl -w kernel.yama.protected_sticky_symlinks=1 sysctl -w vm.mmap_min_addr=65536 ``` - **Windows (PageHeap)**: - 全局启用: ```cmd gflags /p /enable YourProgram.exe /full ``` - 仅针对特定堆: ```cmd gflags /i YourProgram.exe +htc ``` ### 3. **插入自定义内存校验点** 在代码中关键位置添加内存检查函数: ```c #ifdef DEBUG void check_heap_integrity() { #if defined(__linux__) // 触发glibc的堆检查(需要开启MALLOC_CHECK_) malloc_stats(); #elif defined(_WIN32) if (_heapchk() != _HEAPOK) { DebugBreak(); } #endif } #endif ``` - 在调试器中调用: ```gdb (gdb) call check_heap_integrity() ``` ### 4. **利用硬件断点检测内存修改** - 定位疑似被破坏的内存地址后: ```gdb # 设置写断点(当0x12345678地址被写入时中断) (gdb) watch *(int*)0x12345678 ``` - WinDBG: ```windbg ba w4 0x12345678 // 在地址0x12345678处设置写断点 ``` ### 5. **动态分析工具集成** | 工具 | 平台 | 检测能力 | |---------------|---------|------------------------------| | **Valgrind** | Linux | 内存泄漏、越界访问、未初始化数据 | | **Dr.Memory** | Windows | 类似Valgrind的功能 | | **ASan** | 跨平台 | 实时检测地址错误 | ```bash # ASan示例(gcc/clang) gcc -fsanitize=address -g -o program program.c ./program # 运行时自动检测内存错误 ``` ### 诊断流程建议 1. **复现问题**:确保能在受控调试环境中稳定复现缺陷 2. **缩小范围**:通过二分法注释代码确定问题区域 3. **增加日志**:在可疑区域前后添加内存校验点 4. **检查堆栈**:崩溃时立即检查调用栈和线程状态 5. **分析核心转储**: ```bash # Linux gdb -c corefile ./program (gdb) info registers (gdb) x/30i $pc # 反汇编当前指令区域 (gdb) bt full # Windows windbg -y SymbolPath -i ImagePath -z DumpFile.dmp ``` > **关键技巧**:对于堆破坏问题,可在分配内存前后添加守护值(canary values): > ```c > #define GUARD_SIZE 16 > void* protected_malloc(size_t size) { > uint8_t* p = malloc(size + 2*GUARD_SIZE); > memset(p, 0xAA, GUARD_SIZE); // 前守护带 > memset(p+GUARD_SIZE+size, 0xBB, GUARD_SIZE); // 后守护带 > return p + GUARD_SIZE; > } > > void protected_free(void* ptr) { > uint8_t* real_ptr = (uint8_t*)ptr - GUARD_SIZE; > // 检查守护带完整性 > for(int i=0; i<GUARD_SIZE; i++) { > assert(real_ptr[i] == 0xAA); // 检查前守护带 > assert(real_ptr[GUARD_SIZE+size+i] == 0xBB); // 后守护带 > } > free(real_ptr); > } > ``` §§相关问题§§ 1. 如何解读Valgrind报告中的"invalid write of size 4"错误? 2. 在Windows下如何分析堆损坏产生的minidump文件? 3. 有哪些方法可以检测C++程序中的内存泄漏? 4. 如何设置GDB在检测到堆破坏时自动中断? 5. 在嵌入式系统中如何实现内存访问监控?</think>## 调试中检查内存完整性的专业方法 当程序在`free()`操作时触发中断但继续运行正常,表明存在**隐性内存损坏**。以下是系统化的调试检查方法,结合您提供的引用信息: --- ### 一、操作系统级内存检查(内核级) 1. **Linux内存初始化调试** ```bash # 启用详细内存初始化日志 echo 8 > /proc/sys/kernel/printk # 启用KERN_DEBUG输出 echo 4 > /sys/module/mminit/parameters/loglevel ``` - 级别4会记录所有内存初始化细节,帮助检测早期内存损坏[^1] - 通过`dmesg`查看内核日志中的内存分配异常 2. **Windows堆分析(WinDbg)** ```windbg !heap -p -a 0x000830c8 # 分析堆块状态变化 dt _HEAP_ENTRY 0x000830c8 L1 # 查看堆条目元数据 ``` - 对比`HeapAlloc`前后元数据变化(如引用[2]中的0xa6→0xbf) - 检测页边界是否被破坏(Windows以4KB为单位提交内存)[^2] --- ### 二、运行时内存校验技术 #### 1. 守护带检测(Canary Values) ```c #define GUARD_SIZE 16 void* debug_malloc(size_t size) { uint8_t* p = malloc(size + 2*GUARD_SIZE); memset(p, 0xAA, GUARD_SIZE); // 前守护带 memset(p + GUARD_SIZE + size, 0xBB, GUARD_SIZE); // 后守护带 return p + GUARD_SIZE; } void debug_free(void* ptr) { uint8_t* real_ptr = (uint8_t*)ptr - GUARD_SIZE; // 检查守护带完整性 for(int i=0; i<GUARD_SIZE; i++) { assert(real_ptr[i] == 0xAA); // 前守护带校验 assert(real_ptr[GUARD_SIZE+size+i] == 0xBB); // 后守护带校验 } free(real_ptr); } ``` #### 2. 堆一致性检查(glibc) ```c #include <malloc.h> void check_heap() { if (malloc_info(0, stdout) == -1) // 输出XML格式堆状态 perror("malloc_info failed"); if (malloc_stats() == -1) // 打印堆统计信息 perror("malloc_stats failed"); } ``` ```bash # 运行时检查 export MALLOC_CHECK_=3 # 1:打印错误; 2:abort(); 3:两者 ``` --- ### 三、调试器集成检查 #### GDB自动化脚本 ```gdb # gdbinit define memcheck # 在free处设断点并自动检查 b free if $rdi == target_ptr commands x/32gx $rdi-32 # 检查内存内容 call malloc_stats() continue end end ``` 使用: ```bash gdb -x gdbinit --args ./program ``` #### WinDBG堆验证 ```windbg !heap -s # 显示所有堆摘要 !heap -validate # 验证所有堆的完整性 !heap -p -a <address> # 分析特定地址的堆块 ``` --- ### 四、高级工具链方法 | 工具 | 命令/配置 | 检测能力 | |---------------|-----------------------------------|-----------------------------| | **AddressSanitizer** | `-fsanitize=address` | 越界访问/释放后使用/内存泄漏 | | **Valgrind** | `valgrind --tool=memcheck` | 未初始化内存/非法读写 | | **PageHeap** | `gflags /p /enable program.exe`| Windows堆破坏检测 | **关键操作**: ```bash # 1. ASan检测(Linux/macOS) gcc -g -fsanitize=address -fno-omit-frame-pointer -o program program.c # 2. 嵌入式系统内存检查(如ESP32) idf.py -DCMAKE_BUILD_TYPE=debug monitor | grep "heap corruption" ``` --- ### 五、诊断流程建议 1. **复现条件**:通过`stress -m 4`制造内存压力 2. **缩小范围**:使用二分法注释代码段定位损坏区域 3. **检查点**: - 多线程环境中的互斥锁缺失 - 跨模块内存传递时的所有权混淆 - 结构体填充对齐问题(使用`#pragma pack(1)`验证) 4. **核心转储分析**: ```bash ulimit -c unlimited ./program # 崩溃后 gdb program core -ex "info registers" -ex "x/20i $pc" -ex "thread apply all bt" ``` > **提示**:间歇性堆损坏90%源于多线程同步问题或数组越界。优先检查共享内存区域的访问同步性。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值