2011-12-18 15 views
6

Un progetto C++ su cui sto lavorando termina dopo aver generato un'eccezione di prima scelta. Ciò si verifica in Visual Studio 2008 in modalità debug quando provo per la prima volta ad accedere a map<pair<int,int>, int> che contiene una singola coppia chiave-valore. Non c'è nulla di logicamente sbagliato nel codice.C++: Come posso risolvere un'eccezione di prima scelta causata da un punto sconosciuto?

Ho letto le eccezioni di prima scelta e ho capito che potrebbero non essere sempre problematiche. Tuttavia ho provato a rompere tutte queste eccezioni e, come previsto, ne sono stati generati diversi che non causano problemi.

La classe su cui sto lavorando è molto grande e contiene molte allocazioni di memoria personalizzate. Suppongo che in qualche modo uno di questi stia causando il problema. Tuttavia ho passato diverse ore a cercare di trovare un modo per identificare cosa sta andando male e non sono stato in grado di farlo.

L'uscita di eccezione di prima scelta è elencata di seguito. Non è molto utile!

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. 

Sono davvero in difficoltà a questo punto e non sono sicuro di come procedere.

Qualcuno può suggerire come affrontare questo problema e identificare esattamente cosa non va? Sarei molto grato per il tuo consiglio.

UPDATE

Ecco il codice relativo. Le interruzioni debugger nella prima istruzione cout elencato nel annidati 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

Ecco un'immagine della descrizione mouseover per la mappa in questione; sembra corrotto come suggerito da Michael Burr.

enter image description here

+2

Non è la prima volta che le eccezioni lo fanno terminare, è l'eccezione non gestita. –

+1

Non conosco MSVS, ma in qualche modo "violazione dell'accesso" mi fa dubitare che non ci sia "niente di sbagliato nel codice" ... –

+0

Si dice "Non c'è niente di logicamente sbagliato nel codice". Tutte le indicazioni finora sono che c'è qualcosa di sbagliato nel codice. Potresti mostrarci la riga di codice (con le relative righe precedenti). –

risposta

9

In generale, per individuare il punto di codice in cui l'applicazione si blocca, è possibile attivare la manipolazione sotto debug/Eccezioni eccezione. In questo caso, si espande l'ultimo ramo e si controlla la violazione di accesso. Ovviamente questo si fermerà su tutte le violazioni di accesso, e non solo su quelle sbagliate (accesso a 0x10). Puoi minimizzare questo attivando la trappola all'ultimo momento conosciuto.

In genere viene rilevato un errore di utilizzo della memoria. Il modo più semplice per determinare la causa di questo tipo di errore è uno strumento di terze parti come BoundChecker che ti urlerà non appena avrai danneggiato la memoria. In mancanza di ciò, il consiglio di Raymond Chen è azzeccato. Scopri quale oggetto è sbagliato e usa la finestra di controllo per vedere quando è cambiato. O in modo più efficiente, utilizzare la funzionalità Punto di interruzione dei dati per interrompere il programma quando i dati in un determinato indirizzo cambiano.

+0

Grazie per questa informazione, Alan. Le mie scuse per aver impiegato così tanto tempo a segnare la tua risposta! – KomodoDave