C++ 应用程序崩溃说:访问冲突读取位置
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/974264/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Application crashes says : Access violation reading location
提问by Rakesh Agarwal
My application crashes after running for around 18 hours. I am not able to debug the point in the code where it actually crashes. I checked the call stack- it does not provide any information as such. The last few calls in the call stack are greyed out-meaning I cannot see the code of that part-they all belong to MFC libraries.
我的应用程序运行大约 18 小时后崩溃。我无法调试代码中实际崩溃的点。我检查了调用堆栈 - 它没有提供任何信息。调用堆栈中的最后几个调用是灰色的——意味着我看不到那部分的代码——它们都属于 MFC 库。
However, I get this 'MicroSoft Visual Studio' pop-up when it crashes which says :
但是,当它崩溃时,我收到了这个“MicroSoft Visual Studio”弹出窗口,上面写着:
Unhandled exception at 0x7c809e8a in NIMCAsst.exe: 0xC0000005: Access violation reading location 0x154c6000.
NIMCAsst.exe 中 0x7c809e8a 处未处理的异常:0xC0000005:访问冲突读取位置 0x154c6000。
Could the above information be useful to understand where it is crashing.Is there any software that could tell me a particular memory address is held by which variable in the code.
以上信息是否有助于了解它在哪里崩溃。是否有任何软件可以告诉我特定的内存地址由代码中的哪个变量保存。
回答by Patrick
If you can't catch the exception sometimes you just have to go through your code line by line, very unpleasant but I'd put money on it being your code not in MFC (always is with my bugs). Check how you're using memory and what you're passing into the MFC functions extra carefully.
如果您有时无法捕获异常,则您只需要逐行检查代码,这很不愉快,但我会花钱,因为您的代码不在 MFC 中(总是与我的错误有关)。仔细检查您如何使用内存以及您传递给 MFC 函数的内容。
回答by 1800 INFORMATION
Probably the crash is caused by a buffer overflow or other type of memory corruption. This has overwritten some part of the stack holding the return address which has made the debugger unable to reconstruct the stack trace correctly. Or, that the code that caused the crash, you do not have correct sybols for (if the stack trace shows a module name, this would be the case).
崩溃可能是由缓冲区溢出或其他类型的内存损坏引起的。这已经覆盖了保存返回地址的堆栈的某些部分,这使得调试器无法正确重建堆栈跟踪。或者,导致崩溃的代码,您没有正确的符号(如果堆栈跟踪显示模块名称,就是这种情况)。
My first guess would be to examine the code calling the code that crashed for possible issues that might have caused it. Do you get any other exceptions or error conditions before the crash? Maybe you are ignoring an error return? Did you try using the Debug Heap? What about adplus? Application verifierto turn on heap checks?
我的第一个猜测是检查调用可能导致崩溃的可能问题的代码的代码。在崩溃之前您是否收到任何其他异常或错误条件?也许您忽略了错误返回?您是否尝试使用调试堆?什么ADPlus的?应用程序验证程序打开堆检查?
Other possibilities include to run a tool like pclint over the code to check for obvious issues of memory use. Are you using threads? Maybe there is a race condition. The list could go on forever really.
其他可能性包括在代码上运行 pclint 之类的工具以检查明显的内存使用问题。你在使用线程吗?也许存在竞争条件。这个名单真的可以永远持续下去。
回答by Pim
The above information only tells you which memory was accessed illegally.
以上信息仅告诉您哪些内存被非法访问。
You can use exception handling to narrow down the place where the problem occurs, but then you need at least an idea in which corner to seek.
您可以使用异常处理来缩小出现问题的位置,但是您至少需要知道在哪个角落寻找。
You say that you're seeing the call stack, that suggests you're using a debugger. The source code of MFC is available (but perhaps not with all vc++ editions), so in principle one can trace through it. Which VC++ version are you using?
您说您正在查看调用堆栈,这表明您正在使用调试器。MFC 的源代码是可用的(但可能不是所有的 vc++ 版本),所以原则上可以通过它进行跟踪。您使用的是哪个 VC++ 版本?
The fact that the bug takes so long to occur suggests that it is memory corruption. Some other function writes to a location that it doesn't own. This works a long time, but finally the function alters a pointer that MCF needs, and after a while MFC accesses the pointer and you are notified.
该错误需要很长时间才能发生的事实表明它是内存损坏。其他一些函数写入不属于它的位置。这工作了很长时间,但最终该函数更改了 MCF 需要的指针,一段时间后 MFC 访问该指针并通知您。
Sometimes, the 'location' can be recognized as data, in which case you have a hint. F.e. if the error said:
有时,“位置”可以被识别为数据,在这种情况下,您有一个提示。Fe 如果错误说:
Access violation reading location 0x31323334
访问冲突读取位置 0x31323334
you'd recognize this as a part of an ASCII string "1234", and this might lead you to the culprit.
您会将此识别为 ASCII 字符串“1234”的一部分,这可能会将您引向罪魁祸首。
回答by Matthew Flaschen
As Patrick says, it's almost definitely your code giving MFC invalid values. One guess would be you're passing in an incorrect length so the library is reading too far. But there are really a multitude of possible causes.
正如帕特里克所说,几乎肯定是您的代码给出了 MFC 无效值。一种猜测是你传入的长度不正确,所以图书馆读得太远了。但确实有很多可能的原因。
回答by RED SOFT ADAIR
Is the crash clearly reproducible?
崩溃是否可以明显重现?
If yes, Use Logfiles! You should use a logfile and add a number statements that just log the source file/line number passed. Start with a few statements at the entrypoint (main event handler) and the most common execution paths. After the crash inspect the last entry in the logfile. Then add new entries down the path/paths that must have been passed etc. Usually after a few iterations of this work you will find the point of failure. In case of your long wait time the log file might become huge and each iteration will take another 18 hours. You may need to add some technique of rotating log files etc. But with this technique i was able to find some comparable bugs.
如果是,请使用日志文件!您应该使用日志文件并添加一个仅记录传递的源文件/行号的数字语句。从入口点(主事件处理程序)和最常见的执行路径处的一些语句开始。崩溃后检查日志文件中的最后一个条目。然后在必须通过的路径/路径下添加新条目等。通常在此工作的几次迭代后,您会发现故障点。如果等待时间过长,日志文件可能会变得很大,每次迭代将再花费 18 小时。您可能需要添加一些旋转日志文件等的技术。但是通过这种技术,我能够找到一些类似的错误。
Some more questions:
还有一些问题:
Is your app multithreaded?
你的应用是多线程的吗?
Does it use any arrays not managed by stl or comparable containers (does it use C-Strings, C/C++-Arrays etc)?
它是否使用任何不受 stl 或类似容器管理的数组(它是否使用 C-Strings、C/C++-Arrays 等)?
回答by Justin
Try attaching a debugger to the process and have the debugger break on access violations.
尝试将调试器附加到进程并让调试器在访问冲突时中断。
If this isnt possible then we use a tool called "User mode process dumper" to create a memory dump of the process at the point where the access violation happened. You can find this for download here:
如果这是不可能的,那么我们使用名为“用户模式进程转储程序”的工具在发生访问冲突的点创建进程的内存转储。你可以在这里找到这个下载:
How it works: You configure rules on a per-process (or optionally system-wide) basis, and have the tool create either a minidump or a full dump at the point where it detects any one of a list of exceptions - one of them being an access violation. After the dump has been made the application continues as normal (and so if the access violation is unhandled, you will then see this dialog).
工作原理:您在每个进程(或可选的系统范围)的基础上配置规则,并让该工具在检测到异常列表中的任何一个时创建小型转储或完整转储 - 其中之一是访问冲突。转储完成后,应用程序将继续正常运行(因此,如果访问冲突未得到处理,您将看到此对话框)。
Note that ALL access violations in your process are captured - even those that are then later handled, also a full dump can create a while to create depending on the amount of memory the application is using (10-20 seconds for a process consuming 100-200 MB of private memory). For this reason it's probably not a good idea to enable it system-wide.
请注意,您的进程中的所有访问冲突都会被捕获 - 即使是稍后处理的那些,也可以根据应用程序使用的内存量创建一段时间(对于消耗 100- 200 MB 的私有内存)。因此,在系统范围内启用它可能不是一个好主意。
You should then be able to analyse the dump using tools like WinDbg (http://www.microsoft.com/whdc/devtools/debugging/default.mspx) to figure out what happened - in most cases you will find that you only need a minidump, not a full dump (however if your application doesnt use much memory then there arent really many drawbacks of having a full dump other than the size of the dump and the time it takes to create the dump).
然后,您应该能够使用 WinDbg ( http://www.microsoft.com/whdc/devtools/debugging/default.mspx) 之类的工具分析转储以找出发生了什么 - 在大多数情况下,您会发现您只需要小型转储,而不是完全转储(但是,如果您的应用程序不使用太多内存,那么除了转储的大小和创建转储所需的时间之外,完全转储并没有很多缺点)。
Finally, be warned that debugging access violations using WinDbg can be a fairly involed and complex process - if you can get a stack trace another way then you might want to try that first.
最后,请注意,使用 WinDbg 调试访问冲突可能是一个相当复杂的过程 - 如果您可以通过其他方式获得堆栈跟踪,那么您可能想先尝试一下。
回答by Naga
This is the cause of possible memory leak, there are various blogs could teach on checking for memory leaks in application, you simply make observations on Physical Memory of the process from Windows Task Manager, you could find at some stage where memory keep increasing & run out of memory. You can also try running with windbg tool to identify memory leaks in your code. I havent used this tool just giving some heads up on this.
这是可能的内存泄漏的原因,有各种博客可以教检查应用程序中的内存泄漏,您只需从 Windows 任务管理器中观察进程的物理内存,您就会发现在某个阶段内存不断增加并运行内存不足。您还可以尝试使用 windbg 工具运行以识别代码中的内存泄漏。我还没有使用过这个工具,只是对此有所了解。