作者: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程序查错之内存访问异常的更多相关文章

  1. Instruments的使用 逻辑查错,内存泄漏分析等工具集

    原创文章,转载请注明 XCode 开发后期,要对代码进行改进和优化,查内存泄漏是其中一项重要工作,今天下午偷了点时间,把前段时间的代码稍微整理了一下,顺带用了下这个工具,还真发现了些问题.这里记录一下 ...

  2. C++异常机制的实现方式和开销分析 (大图,编译器会为每个函数增加EHDL结构,组成一个单向链表,非常著名的“内存访问违例”出错对话框就是该机制的一种体现)

    白杨 http://baiy.cn 在我几年前开始写<C++编码规范与指导>一文时,就已经规划着要加入这样一篇讨论 C++ 异常机制的文章了.没想到时隔几年以后才有机会把这个尾巴补完 :- ...

  3. VC程序异常中断的原因

    自己编写的VC程序,编译调试通过,运行良好,然后关闭运行界面,就弹出一个“已经触发一个中断”的提示,然后断点就停在了下面这个中断处. _CRTIMP void _cdecl _CrtDbgBreak( ...

  4. 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: ...

  5. 使用_CRTDBG_LEAK_CHECK_DF检查VC程序的内存泄漏(转)

    我们知道,MFC程序如果检测到存在内存泄漏,退出程序的时候会在调试窗口提醒内存泄漏.例如: class CMyApp : public CWinApp{public:BOOL InitApplicat ...

  6. Java内存区域与内存溢出异常(JVM学习系列1)

    相对于C.C++等语言来说,Java语言一个很美好的特性就是自动内存管理机制.C语言等在申请堆内存时,需要malloc内存,用完还有手动进行free操作,若程序员忘记回收内存,那这块内存就只能在进程退 ...

  7. 1.java内存区域与内存溢出异常

    1.java运行时数据区如图所示: 2.每个区域的功能 (1)程序计数器(寄存器) 当前线程所执行的字节码的行号指示器 为了线程切换后能够恢复到正确的执行位置,因此每个线程拥有自己独立的程序计数器 如 ...

  8. JVM内存区域异常分析

    在Java虚拟机规范描述中,除程序计数器外,其他几个运行时区域都有可能发生OutOfMemoryError异常.接下来将对各区域分别进行分析介绍,内容包括触发各区域OutOfMemoryError异常 ...

  9. JVM内存区域与内存溢出异常

    Java虚拟机在执行java程序时会把它所管理的内存会分为若干个不同的数据区域,不同的区域在内存不足时会抛出不同的异常. >>运行时数据区域的划分 (1)程序计数器程序计数器(Progra ...

随机推荐

  1. 重拾C,一天一点点_4_随想

    刚才顺便又把二分默写了一遍,还好,这次比较顺利.算法这一块,一直是自己一块痛处,有时感觉自己的脑瓜子怎么就这么笨,后一想觉得肯定是锈逗了,确实啊,这么长时间不思考的脑子能机灵到哪呢?早就意识到这个问题 ...

  2. Cisco IOS Basic CLI Configuration : Switch Port Command

    Cisco IOS Basic CLI Configuration : Switch Port Command 1.  Basic Switch>en Switch#conf t Enter c ...

  3. 菜鸟学习Struts——简易计算器

    这是学习Struts的一个简单的例子文件结构如下: 1.配置Struts环境 2.新建input.jsp,success.jsp,error.jsp input.jsp代码如下: <%@ pag ...

  4. 微软职位内部推荐-Sr. Dev Lead

    微软近期Open的职位: JD 如果你想试试这个职位,请跟我联系,我是微软的员工,可以做内部推荐.发你的中英文简历到我的邮箱:Nicholas.lu.mail(at)gmail.com

  5. ASP.NET Web – 状态管理

    状态类型 客户端或服务器资源 有效时间 ViewState 客户端 只在一个页面中 Cookie 客户端 关闭浏览器时会删除临时cookie,永久cookie存储在客户系统的磁盘上 Session 服 ...

  6. WebClient

    Mircsoft在dotnet1.1框架下提供的向 URI 标识的资源发送数据和从 URI 标识的资源接收数据的公共方法.通过这个类,大家可以在脱离浏览器的基础上模拟浏览器对互联网上的资源的访问和发送 ...

  7. mysql注入绕过的一些技巧

    虽然mysql + php的开发中可以使用pdo中,但是有些老久的程序没有使用,或其他原因 1.注释绕过 select/*comment*/user/*zzsdsdsf*/from mysql.use ...

  8. Timer定时器

    try { mTimerGoOut = new Timer(); SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy-MM-dd" ...

  9. Matlab中unifrnd函数使用解析

    1.生成N阶[a,b]均匀分布数组 >> unifrnd(3,5,5,5) ans = 3.8651 4.6677 4.8115 4.3456 4.8560 4.0241 3.4079 3 ...

  10. [转载]MongoDB 标准连接字符串

    MongoDB 标准连接字符串 mongodb://[username:password@]host1[:port1][,host2[:port2],…[,hostN[:portN]]][/[data ...