作者: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. js中的数组Array定义与sort方法使用示例

    Array的定义及sort方法使用示例 Array数组相当于java中的ArrayList  定义方法:  1:使用new Array(5  )创建数组 var ary = new Array(5): ...

  2. QQ好友列表向左滑动出现置顶、删除--第三方开源--SwipeMenuListView

    SwipeMenuListView是在github上的第三方开源项目,该项目在github上的链接地址是:https://github.com/baoyongzhang/SwipeMenuListVi ...

  3. Android中表示尺寸的六种度量单位

    本文章来自:http://my.eoe.cn/lakeside/archive/4831.html in:Inches - 表示英寸,是屏幕的物理尺寸,每英寸等于2.54厘米.平时说手机屏幕4(英)寸 ...

  4. Python原始套接字编程

    在实验中需要自己构造单独的HTTP数据报文,而使用SOCK_STREAM进行发送数据包,需要进行完整的TCP交互. 因此想使用原始套接字进行编程,直接构造数据包,并在IP层进行发送,即采用SOCK_R ...

  5. require.js入门指南(二)

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  6. DRP PK 牛腩新闻发布系统

    一.JSP与ASP (1)Web服务器的支持:大多数通用的Web服务器如:Apache.Netscape和Microsoft IIS都支持JSP页面,只有微软本身的Microsoft IIS和Pers ...

  7. MySQL 简洁连接数据库方式

    OS  :   CentOS 6.3 DB  :  5.5.14 MySQL连接数据库的方式很多: 1.[root@db01 bin]# ./mysql -uroot -p 2.[root@db01 ...

  8. unity项目实现“再按一次退出程序”提示功能

    unity项目,再按一次退出程序,按第一次做提示,再按一次,程序退出. float _waitTime = 2f;//前后两次按退出间隔时间 void OnGUI() { ) { GUI.Label( ...

  9. linux 命令grep

    linux 命令grep grep命令用来搜索文本,或从给定的文件中搜索行内包含了给定字符串或单词的文件.通常来说,grep显示匹配的行.使用grep来搜索包括一个或多个正则表达式匹配到的文本行,然后 ...

  10. Build Settings

    Add Open Scenes 选择一个关卡,使其处于打开状态,在菜单栏选择 File -> Build Settings 打开Build Settings窗口.选择 Add Open Scen ...