C++:如何解决在未知点引起的第一次机会异常?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8555573/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 18:47:52  来源:igfitidea点击:

C++ : How can I solve a first-chance exception caused at an unknown point?

c++visual-studio-2008first-chance-exception

提问by KomodoDave

A C++ project I'm working on terminates upon throwing a first-chance exception. This occurs in Visual Studio 2008 in Debug mode when I first try to access a map<pair<int,int>, int>which contains a single key-value pair. There is nothing logically wrong with the code.

我正在处理的 C++ 项目在抛出第一次机会异常时终止。当我第一次尝试访问map<pair<int,int>, int>包含单个键值对的 a时,在调试模式下的 Visual Studio 2008 中会发生这种情况。代码在逻辑上没有任何错误。

I've read up on first-chance exceptions and understand they may not always be problematic. Nonetheless I tried breaking at all such exceptions, and as expected found several are generated which cause no issue.

我已经阅读了第一次机会的例外情况,并了解它们可能并不总是有问题。尽管如此,我尝试打破所有此类异常,并且如预期的那样发现生成了几个不会导致问题的异常。

The class I'm working on is very large and contains many custom memory allocations. I surmise that somehow one of these is causing the problem. However I've spent several hours attempting to find a way to identify what's going wrong, and have been unable to do so.

我正在处理的类非常大,并且包含许多自定义内存分配。我推测其中之一以某种方式导致了问题。但是,我花了几个小时试图找到一种方法来确定出了什么问题,但一直无法做到。

The first-chance exception output is listed below. It isn't very helpful!

下面列出了第一次机会异常输出。这不是很有帮助!

First-chance exception at 0x762cd09c in theapp.exe: 0xC0000005: Access violation reading location 0x6c696d00.
First-chance exception at 0x762cd09c in theapp.exe: 0xC0000005: Access violation reading location 0x6c696d00.
First-chance exception at 0x762cd09c in theapp.exe: 0xC0000005: Access violation reading location 0x6c696d00.
First-chance exception at 0x762cd09c in theapp.exe: 0xC0000005: Access violation reading location 0x6c696d00.
First-chance exception at 0x762cd09c in theapp.exe: 0xC0000005: Access violation reading location 0x6c696d00.
First-chance exception at 0x762cd09c in theapp.exe: 0xC0000005: Access violation reading location 0x6c696d00.
First-chance exception at 0x762cd09c in theapp.exe: 0xC0000005: Access violation reading location 0x6c696d00.
First-chance exception at 0x762cd09c in theapp.exe: 0xC0000005: Access violation reading location 0x6c696d00.
First-chance exception at 0x762cd09c in theapp.exe: 0xC0000005: Access violation reading location 0x6c696d00.
First-chance exception at 0x762cd09c in theapp.exe: 0xC0000005: Access violation reading location 0x6c696d00.
First-chance exception at 0x762cd09c in theapp.exe: 0xC0000005: Access violation reading location 0x6c696d00.
First-chance exception at 0x762cd09c in theapp.exe: 0xC0000005: Access violation reading location 0x6c696d00.
First-chance exception at 0x762cd09c in theapp.exe: 0xC0000005: Access violation reading location 0x6c696d00.
First-chance exception at 0x762cd09c in theapp.exe: 0xC0000005: Access violation reading location 0x6c696d00.
First-chance exception at 0x762cd09c in theapp.exe: 0xC0000005: Access violation reading location 0x6c696d00.
First-chance exception at 0x0050ae33 in theapp.exe: 0xC0000005: Access violation reading location 0x00000010.
Unhandled exception at 0x0050ae33 in theapp.exe: 0xC0000005: Access violation reading location 0x00000010.

I'm really struggling at this point, and am unsure how to proceed.

在这一点上我真的很挣扎,我不确定如何继续。

Can anyone suggest how I might tackle this problem, and identify exactly what's going wrong? I'd be very grateful for your advice.

谁能建议我如何解决这个问题,并确切地确定出了什么问题?我将非常感谢您的建议。

UPDATE

更新

Here's the related code. The debugger breaks on the first cout statement listed in the nested FOR:

这是相关的代码。调试器在嵌套 FOR 中列出的第一个 cout 语句处中断:

        // Inside operator() :

        map<pair<int,int>,int> resultIdByStructIds;
        pair<int,int> spair (-1,-1); // Structure pair ids reusable reference.

        int nextMapEntryId = 0;
        int nextNumCandidates = 0;
        // For each remaining candidate.
        for (int ci = 0; ci < numCandidates; ) {
            // If candidate has been mapped or found not viable this mapping round,
            // move past it.
            if (candidatesDoneThisRound[ci] == currentMappingRoundId) {
                ++ci;
                continue;
            }

            Candidate candidate = candidates[ci];
            const int tId = candidate.tVertexId;
            const int pId = candidate.pVertexId;

            // Grab the result for this structure pair.
            // Create it if it doesn't exist.
            // Avoid copying as slight optimisation; simply
            // store pointer to true result instead.
            spair.first = tInfos[tId].structure->id;
            spair.second = pInfos[pId].structure->id;

            // DEBUG
            cout << "resultIdByStructIds size: " << resultIdByStructIds.size() << endl;
            for (map<pair<int,int>,int>::const_iterator ids_id = resultIdByStructIds.begin(); ids_id != resultIdByStructIds.end(); ++ids_id) {
                cout << ids_id->first.first << endl; // * Debugger breaks here.
                cout << ids_id->first.second << endl;
                cout << ids_id->second << endl;
                printf("Structures(%i,%i) => %i\n",ids_id->first.first,ids_id->first.second,ids_id->second);
            }
            //

            // code continues...

UPDATE 2

更新 2

Here's an image of the mouseover description for the map in question; it appears corrupted as Michael Burr suggested.

这是有关地图的鼠标悬停描述的图像;正如迈克尔伯尔所建议的那样,它似乎已损坏。

enter image description here

enter image description here

回答by Alan Baljeu

In general, to pinpoint the spot of code where the app crashes, you can turn on exception handling under Debug/Exceptions. In this case, you would expand the last branch and check Access Violation. Of course that will stop on all the access violations, and not just the bad one (accessing 0x10). You can minimize this by turning on the trap at the last known moment.

一般来说,要查明应用程序崩溃的代码位置,您可以在调试/异常下打开异常处理。在这种情况下,您将展开最后一个分支并检查访问冲突。当然,这将停止所有访问违规,而不仅仅是坏的(访问 0x10)。您可以通过在最后一个已知时刻打开陷阱来最大程度地减少这种情况。

Typically you will discover some memory usage error. The easiest way to determine the cause of this type of error is a third party tool like BoundChecker which will yell at you as soon as you corrupt the memory. Lacking that, Raymond Chen's advice is spot on. Figure out what object is wrong, and use the watch window to see when it changed. Or more efficiently, use the Data Breakpoint feature to have the program stop when the data at a particular address changes.

通常你会发现一些内存使用错误。确定此类错误原因的最简单方法是使用第三方工具,例如 BoundChecker,一旦您损坏内存,它就会对您大喊大叫。缺少这一点,Raymond Chen 的建议是正确的。找出错误的对象,并使用监视窗口查看它何时发生变化。或者更有效地,使用数据断点功能让程序在特定地址处的数据发生更改时停止。