1、内存相关知识点;
1)windows下32位进程,用户态为2G内存,内核态也为2G内存;却别于linux操作系统;
备注:可以通过命令行与管理员权限,启动3G的用户态空间,但是部分内核态的驱动等可能存在问题,需要实际测试。
两个操作系统的设计为什么会存在1G的差别????
2)物理内存与虚拟内存;保留内存与提交内存的却别与实际影响;
物理内存: 实际机箱里面插的物理内存条;在满足操作系统运行的条件下,只影响操作系统下面程序运行的速度,不影响程序的功能。
虚拟内存:从硬盘上面划分的用于物理内存的扩展,对普通程序员影响不大,也可以理解为虚拟内存页;
保留内存与提交内存:一个32位进程的2G的逻辑内存空间的存在形态。2G内存是一个32位进程可以使用的最大空间,OS层面为了提高内存分配的效率,保留内存用户可以不再关心,如果在window XP下面需要通过该参数确认是否发生了内存碎片,当前vista操作系统后,该问题已经不存在。
3)虚拟内存上涨到2G,一般32位应用程序肯定会出现内存不足而产生崩溃; 备注:Calc.exe的内存当前占用为99.440M,不要给任务管理器中的10M迷惑(提交内存),实际经占用了
2.内存函数调用:
3.异常处理流程:
1)windows下进程的运行操作系统提供了完善的异常保护机制 !teb查看某个线程是否添加了异常保护,为了提升异常相应的速度,异常控制块FS放置在Teb的句柄首地址 ExceptionList为异常处理列表,当有异常发生时,windows的处理流程如下 1、线程出现异常时,查询当前进程的调试端口是否打开,如果时直接进行调试状态
2)获取ExceptionList的第一个FS[0]的控制器进行处理异常,如果处理成功则继续运行(如try catch) 也有可能处理完成后,进程退出了,如自动抓取dump功能,直接上在teb上登记了异常处理控制块,写完dump文件后退出了
3)也可以弹出错误框由用户决定是否继续运行,如runtimes error类错误,可以继续运行,如果否则进入下一个异常处理控制块
4)如果所有的控制块都没有处理异常,则进入windows UnhandleExceptionFilter函数控制块进行处理
4.Windbg常用命令:
Windbg:等同于linux下面的GDB,可以直接在客户机器上面远程调试
Version,操作系统版本,异常等崩溃抓取的时间
!peb 进程等相关信息,如属于哪个程序崩溃了,一些环境变量配置是否正确
!runaway 程序运行的时间,如果太短是否属于已启动就崩溃(配置文件等损坏)
!teb
Kv, !heap,lmvm等命令,使用windbg的se指令,wt,bm,windbg自带的事件指令
dps ln(查询最接近的函数符号)
现场崩溃位置查询,找到崩溃的现场整理出崩溃的代码行->进行崩溃代码行分析
.thread --线程控制块
dd/!teb 线程控制块地址
.dps 进行栈信息打印 ------打印整个线程的栈信息
.dps esp esp + 200进行打印 --- 打印部分栈信息
//将64位操作系统的dump切换为32位操作系统环境
.load wow64exts
!sw
//windows异常问题定位
!findstack kernel32!UnhandleExceptionFilter
!findstack ntdll!KiUserExceptionDispatcher
!findstack ntdll!RtlEnterCriticalSection
!cs
//内存泄露
gflags.exe /i Excute.exe
set _NT_SYMBOL_PATH=C:\Users\Symbals
umdh.exe -p:12345 > d:\MemorySnap1.txt
umdh.exe -p:12345 > d:\MemorySnap2.txt
umdh.exe -d d:\MemorySnap1.txt d:\MemorySnap2.txt > d:\MemoryCmp.txt
操作:D:\2.学习文件\window下问题定位\测试dump信息\王根岭
措施: 关闭 New抛异常,当内存不足时,直接返回空指针
5.定位的一般原理与步骤:
1)确认问题属于哪一类,内存泄露、踩内存、死锁、句柄泄露等…………
2)句柄泄露与内存泄露
采用快照的形式,在进程运行的不同时间段抓取不同的snap,然后比较不同时间段的snap的差异类确认内存泄露的代码位置。 需要开启ust (Create user mode stack trace database)
3)踩内存多线程等相关问题,开启页堆进行问题复现。采用的原理:每个内存页都可以单独设置访问属性,申请的内存高地址4K对齐,同时添加一个4K的隔离页面。这样用户如果操作时,只要写越界,就会触发内存访问错误。这个也就是开启页堆后内存上升很快的原因,同linux下面的vrigrande工具
6.辅助工具:
1)使用procexp查看进程是否异常,内存是否异常,句柄是否泄漏,进程是否死锁,线程是否有泄漏等
2)windbg 查看崩溃时候的dump信息,找到崩溃问题
3)内存泄漏使用umdh进行比较,查询到泄漏的代码行------问题能复现
4)句柄泄漏可以直接使用windbg的!htrace进行跟踪,也可以采用umdh进行定位
5)当出现崩溃或者多线程等难浮现问题。直接搭建环境,进行ApplicationVerifier验证
(正式的交付件应该都需要该工具测试,但是只需要关注多线程,内存踩踏类问题)
6)使用dbgdiag等工具进行崩溃、内存泄露等相关分析,可以只开启ust开关
7)内存泄露不能复现,只能借助dbgdiag或者windbg Heap命令进行分析,找到哪块大小的内存出现了泄露
备注:
当前讲解Vista,Win7\8类内部实现类文档比较少,原先的一些工具等有的已经不是很好使用,因此建议由XP的机器,可以先在XP下面进行稳定性测试,出现问题也比较好定位,如!address可以直接查看剩余堆块大小
7.参考资料: