VC程序查错之内存访问异常
作者:langouster
先来看下面这张图,相信很多程序员都见过类似。
---------------------------
test1.exe - 应用程序错误
---------------------------
"0x00401002" 指令引用的 "0x00000000" 内存。该内存不能为 "written"。
要终止程序,请单击“确定”。
要调试程序,请单击“取消”。
---------------------------
确定 取消
---------------------------
从这个对话框中我们可以提到三个有效信息
1.这个一个内存写错误,所以引起这个错误的语句肯定是一个写操作
2.0x00401002这个地址表示的是出错时的EIP地址,换言之是出错的那行语句的错误。
3."0x00000000" 内存说明程序把一段数据写到了空指针上。
这个错误,如果能重现,那没什么说的了,太简单,直接在VS2003上按F5,然后等着出错,出错时VS会自动指向出错的那一行。
我们重点来讲不能重现的情况,比如在测试机器上出现了。对于一个好的程序员是不应该放过这样一个错误的,必须要找到错误的原因并修正,否则将会给产品埋下定时炸弹。
一般我们编译好做好版本时,我们应该备份下每个版本的pdb文件与exe文件,它于exe在同一目录下生成,这个文件对于调试非常重要,会减少很多麻烦。
这时我们需要用上windbg了,它可以从微软官方下载到,安装后它实际上是绿色的,压缩一下就可以拷来拷去。
在出错的机器上运行windbg,界面大致如下:
选择File->Attach To Process,或直接按F6键。出来一个进程选择界面,默认是按进程启动时间排序的,选择你的出错的进程,单击“OK”。
然后要看你方不方便把pdb文件复制到出错的机器上,如果不方便,我们就要把它的出错状态拿回来,慢慢分析,如果能把pdb复制到对方机器上并调试那是最好的。如果不能,我们就输入.dmp /f c:\1.dmp 这个命令,意思是把出错程序的完整状态复制下来保存到c:\1.dmp文件里,然后你把这个文件复制把你的有pdb的机器上,再打开windbg,把1.dmp拖到windbg上。
在File->Symbol Search Path里设置好pdb目录。在命令行中输入!analyze -v。意思是分析错误,经常windbg是分析不出错误的,你可以输入KB试试,这个命令是查看堆栈。
如果看到类似
这样的就表示可以找到原因了,在test1.cpp的第11行出错了。
这里最简单的调错方法,在实际环境中,往往会比这个情况复杂的多,这需要慢慢积累经验。
如果程序是多线程,有时候还需要先找到出错的线程是哪一个,我一般是开一个windbg的堆栈窗口,再开一个windbg的线程窗口,线程一个个点过去,看哪个线程的堆栈中有异常。
下面再来看一种稍微复杂一点的情况,你可能没有办法在用户机器上安装windbg,或者用户只是给了一张出错时的截图,出错的程序可能已经关了。
这时你可以使用IDA,把对应版本的exe文件与pdb放在一个目录里,把exe放进ida里分析,然后按"G"键输入上面窗口中的0x00401002,那行就是有问题的代码,往前面找找一般都有函数名,但这种方法得到不到具体出错的代码行。我们还可以使用windbg可以直接得到出错的代码行,选择File->Open Executable菜单,选择出错的版本的exe,确定,再设置好pdb路径,然后在命令行窗口中输入u 0x00401002,意思是反汇编这个地址,出来如下图这样的结果,上面直接有出错的代码行。
调试分析BUG需要较多的经验,熟能生巧,欢迎大家多多交流。
http://www.langouster.com/HTML/119.html
VC程序查错之内存访问异常的更多相关文章
- Instruments的使用 逻辑查错,内存泄漏分析等工具集
原创文章,转载请注明 XCode 开发后期,要对代码进行改进和优化,查内存泄漏是其中一项重要工作,今天下午偷了点时间,把前段时间的代码稍微整理了一下,顺带用了下这个工具,还真发现了些问题.这里记录一下 ...
- C++异常机制的实现方式和开销分析 (大图,编译器会为每个函数增加EHDL结构,组成一个单向链表,非常著名的“内存访问违例”出错对话框就是该机制的一种体现)
白杨 http://baiy.cn 在我几年前开始写<C++编码规范与指导>一文时,就已经规划着要加入这样一篇讨论 C++ 异常机制的文章了.没想到时隔几年以后才有机会把这个尾巴补完 :- ...
- VC程序异常中断的原因
自己编写的VC程序,编译调试通过,运行良好,然后关闭运行界面,就弹出一个“已经触发一个中断”的提示,然后断点就停在了下面这个中断处. _CRTIMP void _cdecl _CrtDbgBreak( ...
- spring+ibatis问题1—— 程序报错:java.sql.SQLException: Io 异常: Connection reset by peer, socket write error; ”或“java.sql.SQLException 关闭的连接”异常
转自:http://blog.sina.com.cn/s/blog_1549fb0710102whz2.html spring+ibatis程序测试时报错:java.sql.SQLException: ...
- 使用_CRTDBG_LEAK_CHECK_DF检查VC程序的内存泄漏(转)
我们知道,MFC程序如果检测到存在内存泄漏,退出程序的时候会在调试窗口提醒内存泄漏.例如: class CMyApp : public CWinApp{public:BOOL InitApplicat ...
- Java内存区域与内存溢出异常(JVM学习系列1)
相对于C.C++等语言来说,Java语言一个很美好的特性就是自动内存管理机制.C语言等在申请堆内存时,需要malloc内存,用完还有手动进行free操作,若程序员忘记回收内存,那这块内存就只能在进程退 ...
- 1.java内存区域与内存溢出异常
1.java运行时数据区如图所示: 2.每个区域的功能 (1)程序计数器(寄存器) 当前线程所执行的字节码的行号指示器 为了线程切换后能够恢复到正确的执行位置,因此每个线程拥有自己独立的程序计数器 如 ...
- JVM内存区域异常分析
在Java虚拟机规范描述中,除程序计数器外,其他几个运行时区域都有可能发生OutOfMemoryError异常.接下来将对各区域分别进行分析介绍,内容包括触发各区域OutOfMemoryError异常 ...
- JVM内存区域与内存溢出异常
Java虚拟机在执行java程序时会把它所管理的内存会分为若干个不同的数据区域,不同的区域在内存不足时会抛出不同的异常. >>运行时数据区域的划分 (1)程序计数器程序计数器(Progra ...
随机推荐
- ajax 设置Access-Control-Allow-Origin实现跨域访问
ajax跨域访问是一个老问题了,解决方法很多,比较常用的是JSONP方法,JSONP方法是一种非官方方法,而且这种方法只支持GET方式,不如POST方式安全. 即使使用jquery的jsonp方法,t ...
- 解决This system is not registered with RHN
Redhat之所以会出现这个错误是因为没有注册RHN,我们只需要更新一下yum的源就可以了.使用命令 cd /etc/yum.repos.d/ 进入yum的配置目录. 在终端中输入 wget ht ...
- 【Timers】win服务 定时器
win服务: using System.ServiceProcess; 继承 ServiceBase 即可 定时器: private System.Timers.Timer PushOrderTime ...
- Linq小技巧
遍历集合ForEach: listAll.Items.Clear(); List<Users> list = DP.UsersDAO.GetInfoList(); list.ForEach ...
- oracle里如何将两个日期的时间差返回**时**分的格式
SELECT EXTRACT(DAY FROM (sysdate-to_date('2012-03-29 00:00:00','YYYY-MM-DD HH24:MI:ss')) DAY TO SECO ...
- .Xresources 配置文件
安装rxvt-unicode-256color,如果不是这个版本的话VIM配色会显示不正常. ~/.Xresources配置文件如下 !urxvt color scheme: URxvt*backgr ...
- C#之多态
多态是面向对象编程中三大机制之一,其原理建立在"从父类继承而来的子类可以转换为其父类"这个规则之上,换句话说,能用父类的地方,就能用该类的子类.当从父类派生了很多子类时,由于每个子 ...
- Luence简单实现2
上一篇是基于内存存储的,这次的例子是基于本地存储索引库. 上一次的代码稍微修改,代码如下: //创建词法分析器 Analyzer analyzer = new StandardAnalyzer(); ...
- C# IL DASM 使用
IL DASM反编译工具 使用C#的猿人或多或少都会对微软的IL反编译工具(ildasm.exe)有所认识.我最早接触到这工具是公司同事使用他反编译exe程序,进行研读和修改.感觉他还是很强大. IL ...
- K短路
K短路 用dijsktra+A*启发式搜索当点v第K次出堆的时候,这时候求得的路径是k短路.A*算法有一个启发式函数f(p)=g(p)+h(p), 即评估函数=当前值+当前位置到终点的最短距离g(p) ...