已提交内存过大_windows下内存剖析

学习笔记,持续更新中

进程地址空间布局

3cb55afa1ebd4189700bb69e2729d740.png
x64进程地址空间布局
  • 进程地址空间

32位地址空间范围:0x0000 0000 ~ 0xFFFF FFFF(

)。

64位地址空间范围:0x0000 0000 0000 0000 ~ 0xFFFF FFFF FFFE FFFF(

)。
  • NULL指针分区

范围:0x0000 0000 ~ 0x0000 FFFF。

作用:作为非法访问区域,用于内存分配失败,内存非法标记等。

  • 用户区

32位:

范围:0x0001 0000 ~ 0x7FFE FFFF(2GB-128KB)

作用:用户代码访问

特殊设置:如果在boot.ini上设置了/3G,范围从2G扩充为3G,0x0001 0000 ~ 0xBFFE FFFF

x64:

范围:0x0000 0000 0001 0000 ~ 0x0000 7FFF FFFE FFFF(128TB - 128KB)

作用:用户代码访问

  • 共享内核区

32位:

范围:0x8000 0000 ~ 0xFFFF FFFF

作用:内核代码访问

特殊设置:如果在boot.ini上设置了/3G,范围从2G缩小为1G,0xC000 0000 ~ 0xFFFF FFFF

x64:

范围:0xFFFF 8000 0000 0000 ~ 0xFFFF FFFF FFFF FFFF

作用:内核代码访问

访问属性

Memory Protection Constants (WinNT.h) - Win32 apps​docs.microsoft.com

内存映射

12bd35e3e2184014680ae7dae4392410.png
32位虚拟地址映射过程

PE文件Section解释

节名描述
.text代码
.rdata只读数据,如字符串常量和c++/COM虚表
.data可读/可写数据节。全局变量通常在这个节中
.pdata异常表。它包含一个IMAGE_RUNTIME_FUNCTION_ENTRY结构数组,这个结构与平台体系结构相关。数据目录中索引为IMAGE_DIRECTORY_ENTRY_EXCEPTION的项指向它。用于使用基于表的异常处理的平台,例如IA-64。惟一不使用基于表的异常处理的平台是x86(它使用的是基于堆栈的异常处理)。
.idata导入表。实际上,链接器经常把.idata节合并到其它节中(或者是明确指定的,或者是通过链接器的默认行为)。默认情况下,链接器仅在创建发行版的程序时才把.idata节合并到其它节中。
.edata导出表。当创建要导出函数或数据的可执行文件时,链接器会创建一个.EXP文件。这个.EXP文件包含一个.edata节,这个节被添加到最后的可执行文件中。与.idata节一样,.edata节也经常被合并到.text节或.rdata节中。
.rsrc资源节。这个节是只读的。它不应该被命名为其它名称,也不应该被合并到其它节中。
.bss未初始化的数据节。在最新的链接器创建的可执行文件中很少见到。链接器扩展可执行文件的.data节的VirtualSize域以便容纳未初始化的数据。
.crt添加到可执行文件中的数据,用来支持C++运行时库(CRT)。一个比较好的例子就是用于调用静态C++对象的构造函数和析构函数的指针。
.tls支持使用__declspec(thread)语法创建的线程局部存储变量。它包括数据的初始值,以及运行时需要的附加变量。
.reloc可执行文件中的基址重定位节。通常DLL需要基址重定位信息而EXE并不需要。在创建发行版的程序时,链接器并不为EXE文件生成基址重定位信息。可以使用/FIXED链接器选项移除基址重定位信息。
.sdata通过全局指针(Global Pointer)相对寻址的“短(Short)”可读/可写数据。用于IA-64和其它使用全局指针寄存器的平台上。IA-64平台上正常大小的全局变量在这个节中。
.debug$SOBJ文件中的Codeview格式的调试符号(Symbol)信息。这是一列可变长度的CodeView格式的调试符号记录。
.debug$TOBJ文件中的Codeview格式的调试类型(Type)记录。这是一列可变长度的CodeView格式的调试类型记录。
.debug$P可以在使用预编译头(Precompiled Headers)生成的OBJ文件中找到这个节。
.drectve包含链接器指令,并且只存在于OBJ文件中。这些指令是传递到链接器命令行的ASCII码字符串,例如:-defaultlib:LIBC。指令之间用空格分开。
.didata延迟加载导入数据。可以在非发行版本的可执行文件中找到。在发行版本中,延迟加载数据被合并到其它节中。
.xdata异常处理表。

建立进程

0cc9fde13d228278cd92ac4e5d0e3a40.png
第一次调用exe流程图

数据对齐

如果数据不能对齐,则可能需要通过两次访问内存,这回导致cache miss,降低执行效率。

物理角度看内存分布

6a9886612fb9d121d8cd6b12c1e6a556.png

VMMap内存分析

6a17ad0b3a56daf6559e7030842bee33.png
  • 横着看

Image:

映射可执行文件。

Mapped file:

映射数据文件。

特性:

调用CreateFileMapping,无事发生

调用MapViewOfFile,Size和Committed增加

访问数据,Total WS和Sharable WS增加

调用UnmapViewOfFile,Size,Committed和WS都减少

调用CloseHandle,无事发生

Sharable:

标记为共享的,且以磁盘页面文件作为后备的。

调用CreateFileMapping,磁盘页面文件Committed部分增加

调用MapViewOfFile,Size和Committed增加

访问数据,Total WS和Sharable WS增加

调用UnmapViewOfFile,Size,Committed和WS都减少

调用CloseHandle,磁盘页面文件Committed部分减少

Private Data:

标记为私有的内存分配,如VirtualAlloc。

Heap:

堆内存分配,如new,GlobalAlloc和HeapAlloc等。

Stack:

栈内存分配。

Page table:

内核里面维护当前虚拟地址空间所需要的内存。

Managed Heap:

.NET garbage collector分配和释放

Reserverd:

预留的,尚未使用的内存。

Free:

空闲空间。

Unusable:

不可使用的。

  • 竖着看

Size = Commit + Reserve

Committed = Private + Shareable

Private = Private WS + Private Page File

Total WS = Private WS + Sharable WS

Private WS = 仅属于当前进程的working set

Sharable WS = 可共享的working set

Shared WS = 已经共享的working set,Sharable WS的子集

Shareable下CreateFileMapping访问同一块内存情况探究

802a465acab238ca6d93748c80d01acb.png
各阶段图
  • 程序启动

83431abb2572f29deaaeaef8fb1a0ced.png
  • 第一次调用CreateFileMapping

c8bae5d82cb8ede0561c4220183de9e8.png

第一次调用CreateFileMapping,系统已提交内存增加。

  • 第一次调用MapViewOfFile

377367636341705d0846152c5af1a083.png

fb300ab57b628be9cbf2fe13dc91e63c.png

第一次调用MapViewOfFile导致Size和Committed增加。

  • 第一次访问内存

b1a86fdbf1dbb1034f0d28c0bf37c6e8.png

1e376c756d623b4464e5b82c1dd0dd60.png

第一次访问内存导致Total WS和Shareable WS增加,同时系统已经使用WS(物理内存)增加。

  • 第一次OpenFileMapping

0cac6f347b98e590e2a2d2940e14735e.png
  • 第二次MapViewOfFile

cbe98c20d294b5ee3788e2b147595d98.png

e29313a7a7323b4b099b977829494c62.png

第二次MapViewofFile导致Size和Committed再次上升。

  • 第二次访问内存

a5912d1e38323fc0144c7d9b242c9a8b.png

2d9fb99463abe6db78fcacf06e5455a3.png

第二次访问内存Total WS,Shareable WS和Shared WS再次增加。

  • 第一次调用UnmapViewOfFile

0113776b6c938c3cb56480df73ea5ef4.png

0e2763e56c2d8fe655a0f6aa653f71b4.png

第一次调用UnmapViewOfFile导致其中一块共享内存的Size,Committed,Total WS,Shareable WS,Shared WS都相应地减少,同时另外一块的Shared WS也减少。

  • 第一次调用CloseHandle

372c12e52187d1de1a1dd764ebe38d58.png
  • 第二次调用UnmapViewOfFile

2961b66e70019c9fe35643204d81e81f.png

32ff3a72bd09b84f796f2f505f21ea97.png

第二次调用UnmapViewOfFile导致最后一块共享内存Size,Committed,Total WS,Shareable WS都相应地减少,同时已经使用的WS(物理内存)减少。

  • 第二次调用CloseHandle

214d49d8bf83917051f8f38f63b19e46.png

第二次调用CloseHandle系统已提交内存减少。

内存研究样例

#include 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值