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

1

6

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.

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:

        // 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

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

enter image description here

Fulani answered 18/12, 2011 at 23:7 Comment(10)
It's not the first-chance exceptions that are making it terminate, it is the unhandled exception.Scarbrough
I don't know MSVS, but somehow "access violation" makes me doubt that there's "nothing wrong with the code"...Riyal
You say "There is nothing logically wrong with the code.". All indications so far is that there is something wrong with the code. Could you show us the line of code (with the relevant preceeding lines).Supercharger
Maybe this previous solution will solve your problem #6372213Monaxial
Ok some justification: 'logically' is obviously subjective; I haven't posted code because the class is several thousand lines long. I assumed since the address referred to in the unhandled exception was the same as the preceding First-chance exception that I should describe it as such. Anyway, I will post some code and/or utilise the link you provided, Jamie. Thanks to everyone for your advice, I'll comment again shortly.Fulani
I've posted the relevant code as an update in my question. Any insights?Fulani
Take a look at resultIdByStructIds in the debugger when the exception occurs - I'd bet it has been corrupted somehow. The nature of the corruption might give you an idea of what to do next. For example, a memory breakpoint on a pointer changing some particular corrupt value.Kalidasa
@Michael - I did what you suggested, and indeed the map appears to be corrupted. I've attached an image as another update to my question, above. Does this mean I'm right in thinking a custom memory allocation is causing problems somewhere? How can I best pinpoint how/where the issue arises?Fulani
Step through the code in the debugger. After each step, check resultIdByStructIds. At some point it will become corrupted. That's the step that corrupted it.Zettazeugma
I'll do as you've suggested, thank you Raymond.Fulani
D
9

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.

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.

Doretheadoretta answered 16/2, 2012 at 14:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.