简体   繁体   English

如何在Visual C ++ 9中调试缓冲区溢出?

[英]How to debug a buffer overrun in Visual C++ 9?

I have a huge MMC snapin written in Visual C++ 9. Every once in a while when I hit F5 in MMC mmc.exe crashes. 我有一个用Visual C ++ 9编写的巨大的MMC管理单元。每当我在MMC中遇到F5时,mmc.exe崩溃了。 If I attach a debugger to it I see the following message: 如果我附加调试器,我会看到以下消息:

A buffer overrun has occurred in mmc.exe which has corrupted the program's internal state. mmc.exe中发生缓冲区溢出,破坏了程序的内部状态。 Press Break to debug the program or Continue to terminate the program. 按Break可调试程序或继续终止程序。

For more details please see Help topic 'How to debug Buffer Overrun Issues'. 有关更多详细信息,请参阅帮助主题“如何调试缓冲区溢出问题”。

First of all, there's no How to debug Buffer Overrun Issues topic anywhere. 首先,没有如何在任何地方调试缓冲区溢出问题主题。

When I inspect the call stack I see that it's likely something with security cookies used to guard against stack-allocated buffer overruns: 当我检查调用堆栈时,我发现可能有一些安全cookie用于防止堆栈分配的缓冲区溢出:

MySnapin.dll!__crt_debugger_hook()  Unknown
MySnapin.dll!__report_gsfailure()  Line 315 + 0x7 bytes C
mssvcr90d.dll!ValidateLocalCookies(void (unsigned int)* CookieCheckFunction=0x1014e2e3, _EH4_SCOPETABLE * ScopeTable=0x10493e48, char * FramePointer=0x0007ebf8)  + 0x57 bytes  C
msvcr90d.dll!_except_handler4_common(unsigned int * CookiePointer=0x104bdcc8, void (unsigned int)* CookieCheckFunction=0x1014e2e3, _EXCEPTION_RECORD * ExceptionRecord=0x0007e764, _EXCEPTION_REGISTRATION_RECORD * EstablisherFrame=0x0007ebe8, _CONTEXT * ContextRecord=0x0007e780, void * DispatcherContext=0x0007e738)  + 0x44 bytes    C
MySnapin.dll!_except_handler4(_EXCEPTION_RECORD * ExceptionRecord=0x0007e764, _EXCEPTION_REGISTRATION_RECORD * EstablisherFrame=0x0007ebe8, _CONTEXT * ContextRecord=0x0007e780, void * DispatcherContext=0x0007e738)  + 0x24 bytes C
ntdll.dll!7c9032a8()    
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll] 
ntdll.dll!7c90327a()    
ntdll.dll!7c92aa0f()    
ntdll.dll!7c90e48a()    
MySnapin.dll!IComponentImpl<CMySnapin>::GetDisplayInfo(_RESULTDATAITEM * pResultDataItem=0x0007edb0)  Line 777 + 0x14 bytes C++
// more Win32 libraries functions follow

I have lots of code and no idea where the buffer overrun might occur and why. 我有很多代码,不知道缓冲区溢出可能发生在哪里以及原因。 I found this forum discussion and specifically the advise to replace all wcscpy-like functions with more secure versions like wcscpy_s() . 我找到了这个论坛的讨论 ,特别是建议用更安全的版本,如wcscpy_s()替换所有类似wcscpy的函数。 I followed the advise and that didn't get me closer to the problem solution. 我遵循了建议,并没有让我更接近问题的解决方案。

How do I debug my code and find why and where the buffer overrun occurs with Visual Studio 2008? 如何调试我的代码并查找Visual Studio 2008发生缓冲区溢出的原因和位置?

Add /RTCs switch to the compiler. 添加/ RTC切换到编译器。 This will enable detection of buffer overruns and underruns at runtime. 这样可以在运行时检测缓冲区溢出和欠载。 When overrun will be detected, program will break exactly in place where it happened rather than giving you postmortem message. 当检测到溢出时,程序将完全打破它发生的位置,而不是给你死后的消息。

If that does not help, then investigate wcscpy_s() calls that you mentioned. 如果这没有帮助,那么调查你提到的wcscpy_s()调用。 Verify that the 'number of elements' has correct value. 验证“元素数量”是否具有正确的值。 I recently fixed buffer overrun caused incorrect usage of wcscpy_s(). 我最近修复了缓冲区溢出导致wcscpy_s()的错误使用。 Here is an example: 这是一个例子:

const int offset = 10;
wchar_t buff[MAXSIZE];
wcscpy_s(buff + offset, MAXSIZE, buff2); 

Notice that buff + offset has MAXSIZE - offset elements, not MAXSIZE. 请注意,buff + offset具有MAXSIZE - 偏移元素,而不是MAXSIZE。

I just had this problem a minute ago, and I was able to solve it. 我刚刚解决了这个问题,我能够解决它。 I searched first on the net with no avail, but I got to this thread. 我首先在网上搜索没有用,但我得到了这个帖子。

Anyways, I am running VS2005 and I have a multi-threaded program. 无论如何,我正在运行VS2005,我有一个多线程程序。 I had to 'guess' which thread caused the problem, but luckily I only have a few. 我不得不'猜测'哪个线程导致了问题,但幸运的是我只有一些。

So, what I did was in that thread I ran through the debugger, stepping through the code at a high level function. 所以,我所做的就是在那个线程中,我通过调试器,在高级函数中逐步执行代码。 I noticed that it always occurred at the same place in the function, so now it was a matter of drilling down. 我注意到它总是发生在函数的同一个地方,所以现在是钻井的问题。

The other thing I would do is step through with the callstack window open making sure that the stack looked okay and just noting when the stack goes haywire. 我要做的另一件事是逐步打开callstack窗口,确保堆栈看起来没问题,只是注意到堆栈何时出现问题。

I finally narrowed down to the line that caused the bug, but it wasn't actually that line. 我终于缩小到导致这个bug的行,但实际上并不是那条线。 It was the line before it. 这是它之前的界限。

So what was the cause for me? 那么我的原因是什么? Well, in short-speak I tried to memcpy a NULL pointer into a valid area of memory. 好吧,简而言之,我试图将一个NULL指针memcpy到一个有效的内存区域。

I'm surprised the VS2005 can't handle this. 我很惊讶VS2005无法处理这个问题。

Anyways, hope that helps. 无论如何,希望有所帮助。 Good luck. 祝好运。

I assume you aren't able to reproduce this reliably. 我假设你无法可靠地重现这一点。

I've successfully used Rational Purify to hunt down a variety of memory problems in the past, but it costs $ and I'm not sure how it would interact with MMC. 我过去成功地使用了Rational Purify来解决各种内存问题,但它花费了多少钱而且我不确定它会如何与MMC交互。

Unless there's some sort of built-in memory debugger you may have to try solving this programmatically. 除非有某种内置内存调试器,否则您可能必须尝试以编程方式解决此问题。 Are you able to remove/disable chunks of functionality to see if the problem manifests itself? 您是否能够删除/禁用功能块以查看问题是否自行显现?

If you have "guesses" about where the problem occurs you can try disabling/changing that code as well. 如果您“猜测”问题发生的位置,您也可以尝试禁用/更改该代码。 Even if you changed the copy functions to _s versions, you still need to be able to reliably handle truncated data. 即使您将复制功能更改为_s版本,您仍然需要能够可靠地处理截断的数据。

I have got this overrun when I wanted to increment a value in a pointer variable like this: 当我想在这样的指针变量中递增一个值时,我得到了这个溢出:

*out_BMask++;
instead 代替
(*out_BMask)++;

where out_BMask was declared as int *out_BMask 其中out_BMask被声明为int *out_BMask
If you did something like me then I hope this will help you ;) 如果你做了像我这样的事情,那么我希望这会对你有帮助;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM