VC++6.0访问违反了当运行调试器
-
22-08-2019 - |
题
我想添加增强到4岁的VC++6.0程序。调试建立运行从命令行,但不是在调试器:它崩溃的一个访问违反内部printf().如果我跳过printf,然后崩溃在malloc()(所谓的内fopen())和我不能跳过这个。
这意味着我不能运行调试器,必须依靠老printf语句看看会发生什么。这显然使得它变得更加困难。
任何知道为什么printf()and malloc()就会失败下运行时VC++调试器?我不擅长这个低级别的东西!
这里是调用堆后访问违反:
_heap_alloc_dbg(unsigned int 24, int 2, const char * 0x0046b3d8 `string', int 225) line 394 + 8 bytes
_nh_malloc_dbg(unsigned int 24, int 0, int 2, const char * 0x0046b3d8 `string', int 225) line 242 + 21 bytes
_malloc_dbg(unsigned int 24, int 2, const char * 0x0046b3d8 `string', int 225) line 163 + 27 bytes
_lock(int 2) line 225 + 19 bytes
_getstream() line 55 + 7 bytes
_fsopen(const char * 0x00468000 `string', const char * 0x00466280 `string', int 64) line 61 + 5 bytes
fopen(const char * 0x00468000 `string', const char * 0x00466280 `string') line 104 + 15 bytes
open_new_log(const char * 0x00468000 `string') line 66 + 14 bytes
log_open(const char * 0x00468000 `string', int 0) line 106 + 9 bytes
Xlog_open(const char * 0x00468000 `string', int 0) line 51 + 13 bytes
service_start(unsigned long 1, char * * 0x009a0e50) line 3152 + 12 bytes
service_init2(char * 0x00471fcc char * NTPROGRAM, char * 0x004723c4 char * NTSERVICE, char * 0x00466540 `string', unsigned long 1, char * * 0x009a0e50) line 508 + 13 bytes
service_init(char * 0x00471fcc char * NTPROGRAM, char * 0x004723c4 char * NTSERVICE, unsigned long 2, char * * 0x009a0e50) line 548
main(unsigned long 2, char * * 0x009a0e50) line 3131
mainCRTStartup() line 206 + 25 bytes
KERNEL32! 7c817067()
这里是调试dissassembly的操作,失败:
0041EA7E jmp _heap_alloc_dbg+2B3h (0041eb23)
0041EA83 mov edx,dword ptr [_lTotalAlloc (004b4294)]
0041EA89 add edx,dword ptr [nSize]
0041EA8C mov dword ptr [_lTotalAlloc (004b4294)],edx
0041EA92 mov eax,[_lCurAlloc (004b429c)]
0041EA97 add eax,dword ptr [nSize]
0041EA9A mov [_lCurAlloc (004b429c)],eax
0041EA9F mov ecx,dword ptr [_lCurAlloc (004b429c)]
0041EAA5 cmp ecx,dword ptr [_lMaxAlloc (004b42a0)]
0041EAAB jbe _heap_alloc_dbg+249h (0041eab9)
0041EAAD mov edx,dword ptr [_lCurAlloc (004b429c)]
0041EAB3 mov dword ptr [_lMaxAlloc (004b42a0)],edx
0041EAB9 cmp dword ptr [_pFirstBlock (004b4298)],0
0041EAC0 je _heap_alloc_dbg+25Fh (0041eacf)
0041EAC2 mov eax,[_pFirstBlock (004b4298)]
0041EAC7 mov ecx,dword ptr [pHead]
0041EACA mov dword ptr [eax+4],ecx
这里是我们的来源,呼吁fopen()并未在malloc()
FILE *open_new_log( const char *logfile )
{
FILE *fp;
int retry = 0;
while( ( fp = fopen( logfile, "w" ) ) == NULL && ++retry < 300 )
Sleep( 1000 );
return( fp );
}
错误我得到的是
Unhandled exception inPISCOOP.exe: 0xC00000005: Access Violation
问候,
---阿利斯泰尔
解决方案
可以使用 _CrtSetDbgFlag()
以使一堆有用堆调试技术。还有其他 CRT调试功能使用应该帮助您跟踪您的问题。
其他提示
当从调试器中运行,不同的堆被使用;这被称为调试堆。这已经从调试器外部使用的堆不同的行为,而且是有帮助你赶上这样一个问题。
请注意在Win32“调试堆”是从VC ++“调试堆”不同;两者都打算做或多或少同样的事情,但是。请参见其描述行为的差异,当你运行应用程序这篇文章下的调试程序。
在这种情况下,你可能已经调用此函数之前,或者通过注销结束或关闭一个堆块的开始损坏堆。
最简单的方法(前提是你的应用程序未使用的内存也广泛)是使整页堆检查(将你的配置是从,这反过来,将所提供的内存页面后放置所谓的防护页面找出确切的发生在你的代码在腐败发生)。
既然你有的Windows调试工具方便,运行以下GFlags命令配置整页堆:
gflags[.exe] /p /enable yourapp.exe /full
注意,你应该提供可执行文件名称的单独(即不带路径前缀!)点击 然后,只需运行在调试器下 - 它会与第一次尝试破坏堆打破。这里不同的是,堆损坏大多延迟它们表现以后,当一个(可能)有效堆操作是有效的缺陷。
请注意,也:
gflags[.exe] /p /enable yourapp.exe /full /backwards
另外将防护页面把你分配之前。
单独与/ p开关运行将在效果目前显示堆页面选项。
您可以有一个堆损坏错误。你的应用程序可能已经损坏堆open_new_log()
被调用之前。
我怀疑jmattias是正确的。该问题的根本原因可能是别的地方比在那里崩溃。
很多事情可能会导致堆腐败。
- 写过(或开始)的存储器模块,是分配。
- 释放一个指两次,或者释放的指针不是分配。
- 多线程序及连接与单螺纹(不thread safe)RTL。
- 分配存储器从一堆和释放在另一堆。
- 等等, 等等,
因为你使用C++,可以使用_CrtSetDbgFlag()特征的调试堆把上的错误检查。你可以把它设置检查完整性的堆在每个呼吁malloc或免费的。将运行非常缓慢,但它应该确定错误是给你的。
搜索_CrtSetDbgFlag在编译文档。
我怀疑存在与不同版本的C ++运行比应用程序的其余部分的编译的DLL。这经常会导致“存储器在地址XXX不能被‘读’/‘写’”违规。