不要放过User breakpoint called from code at [0x77000000]
Mindon 2009-8-12
摘编自www.diybl.com 作者:匿名 User breakpoint called from code at 0x7740240f 已解决
尊重原创
VC调试程序时,程序报出“User breakpoint called from code at 0x77000000[程序地址]”对话框。从表面上看,这好像是用户设置断点引起的错误。这样的对话框很容易误导程序员,认为是个断点提示,所以也就没去管它。但是找遍了源代码也没有发现哪里有设置断点,这很奇怪。而且这个对话框每次必报。上网查找才发现这个问题原来是程序堆内存被破坏导致的。至于为啥报用户断点这个对话框不理解。
这种问题通常是程序堆内存被破坏。程序报出这样的对话框有时不会对整个程序造成破坏,依然能够继续运行,但千万不要放过,像这种破坏堆内存的隐藏BUG,有可能造成整个软件的crash。若是release版本也许什么提示都没有,这是因为在debug下,操作系统用DebugWin32Heap来代替正常的heap分配内存空间。在这个堆上的任何操作,debug的堆管理器会检查堆的数据完整性,如果它发现了一个错误,就会报告一个消息上来。 既然是delete的时候出了问题,那就是这个程序很可能去访问了“非法”的内存,非法内存是指不是由你的程序分配的内存块,但是被你的程序在某种情况下访问到了,当然这是堆上的情况,所以在release下可能一时不会出问题。程序在堆上分配了那么多对象,到底哪次分配出了问题?这还是很难定位到错误,用BoundsChecker完整跑一遍是一个好办法,但是比较麻烦。试想如果在每次分配的内存块边界做限制,设置为虚拟内存,也就是NO_ACCESS(不可访问),那程序试图读写这个地方的时候,就会出错,程序会马上断下来,也就是所谓的PageHeap机制。
微软提供了PageHeap机制来方便程序员查找堆破坏问题。 要让程序启用Full Page Heap机制,有2种方法。
1.直接修改注册表
exe:
HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion/Image File Execution Options/appName.exe下增加如下设置,
属性名:GlobalFlag,字符串类型,值:x02200000
属性名:PageHeapFlags,字符串类型,值:0x3
属性名:VerifierFlags,DWORD类型,值:1
其中appName.exe为你正在调试的程序文件名(不需要路径)
dll:
GlobalFlag,字符串类型,值是0x02000000
PageHeapTargetDlls,字符串类型,值是调试的dll名称,不带路径
VerifierFlags,DWORD类型,值是00000001
PageHeapFlags,字符串类型,0x403 注册表的子健值应该是dll依附的exe程序名。
2.使用Debugging Tools for Windows[http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx]
exe:
运行 gflags –p /enable appName.exe /full 即可自动帮你添加上述注册表值。
gflags在Debugging Tools for Windows的安装目录下
dll:
gflags –p /enable appName.exe /full /dlls dllName.dll
再次debug下调试程序,User breakpoint called from code at不会再出现了,而出现的是未处理的异常对话框,且程序断在了出错的地方。
Good luck!
Mindon 2009-8-12