Domanda

Questo è abbastanza strano per me, ma sto ricevendo un errore inaspettato e casuale di segmentazione quando lancio il mio programma. Alcune volte funziona, a volte lo si blocca .. Il debugger di Dev-C ++ mi indica una riga del file: stl_construct.h

/**
   * @if maint
   * Constructs an object in existing memory by invoking an allocated
   * object's constructor with an initializer.
   * @endif
   */
  template<typename _T1, typename _T2>
    inline void
    _Construct(_T1* __p, const _T2& __value)
    {
      // _GLIBCXX_RESOLVE_LIB_DEFECTS
      // 402. wrong new expression in [some_]allocator::construct
     -> ::new(static_cast<void*>(__p)) _T1(__value);
    }

Sto utilizzando lo STL ampiamente dal modo .. cosa devo fare per individuare l'origine del segfault? Ci sono strumenti che possono aiutare? Quali sono le ragioni che possono portare a crash casuali come questo.

Modifica:

Il mio programma conta circa 5000 linee di codice. Non so che cosa pezzo di codice devo mostrare, al fine di avere un aiuto dal momento che non ho alcun indizio circa l'origine del problema, tutto quello che ho dal debugger è che ha a che fare con la STL.

Modifica:

mi sono trasferito a Code::Blocks ora, qui è lo stack di chiamate:

#0 00464635 std::_Construct<std::pair<double const, int>, std::pair<double const, int> >(__p=0xb543e8, __value=@0x10) (C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_construct.h:81)
#1 00462306 std::_Rb_tree<double, std::pair<double const, int>, std::_Select1st<std::pair<double const, int> >, std::less<double>, std::allocator<std::pair<double const, int> > >::_M_create_node(this=0x406fe50, __x=@0x10) (C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_tree.h:367)
#2 00461DA7 std::_Rb_tree<double, std::pair<double const, int>, std::_Select1st<std::pair<double const, int> >, std::less<double>, std::allocator<std::pair<double const, int> > >::_M_clone_node(this=0x406fe50, __x=0x0) (C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_tree.h:379)
#3 004625C6 std::_Rb_tree<double, std::pair<double const, int>, std::_Select1st<std::pair<double const, int> >, std::less<double>, std::allocator<std::pair<double const, int> > >::_M_copy(this=0x406fe50, __x=0x0, __p=0x406fe54) (C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_tree.h:1029)
#4 00462A9D std::_Rb_tree<double, std::pair<double const, int>, std::_Select1st<std::pair<double const, int> >, std::less<double>, std::allocator<std::pair<double const, int> > >::_Rb_tree(this=0x406fe50, __x=@0xb59a7c) (C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_tree.h:559)
#5 0045A928 std::map<double, int, std::less<double>, std::allocator<std::pair<double const, int> > >::map(this=0x406fe50, __x=@0xb59a7c) (C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_map.h:166)
#6 0040B7E2 VehicleManager::get_vehicles_distances(this=0xb59a50) (C:/Program Files/CodeBlocks/MinGW/projects/AHS/VehicleManager.cpp:232)
#7 00407BDA Supervisor::IsMergeInstruction(id_vehicle=1) (C:/Program Files/CodeBlocks/MinGW/projects/AHS/Supervisor.cpp:77)
#8 00408430 CheckingInstructionsThread(arg=0x476100) (C:/Program Files/CodeBlocks/MinGW/projects/AHS/Supervisor.cpp:264)
#9 00413950 _glfwNewThread@4() (??:??)
#10 75A24911    KERNEL32!AcquireSRWLockExclusive() (C:\Windows\system32\kernel32.dll:??)
#11 00476100    std::__ioinit() (??:??)
#12 0406FFD4    ??() (??:??)
#13 76E5E4B6    ntdll!RtlInitializeNtUserPfn() (C:\Windows\system32\ntdll.dll:??)
#14 00476100    std::__ioinit() (??:??)
#15 70266582    ??() (??:??)
#16 00000000    ??() (??:??)

Un paio di precisazioni:

1 / E 'un'applicazione multi-filettata. 2 / Il metodo: get_vehicles_distances (); restituisce una mappa. 3 / E 'possibile che la mappa non è initalised dal momento in cui è chiamato da IsMergeInstruction ();

Modifica:

A quanto pare la linea che causa il segfault è:

vehicles_distances_.erase(vehicles_distances_.begin(), vehicles_distances_.end());

Dove vehicles_distances_ è la mappa. Questa linea è una parte del metodo: VehicleManager :: MoveAllVehicles ();

void VehicleManager::MoveAllVehicles() {

     vehicles_distances_.erase(vehicles_distances_.begin(), vehicles_distances_.end());

     vector<Vehicle>::iterator iter_end = VehicleManager::vehicles_.end();
     for(vector<Vehicle>::iterator iter = VehicleManager::vehicles_.begin();
     iter != iter_end; ++iter) {

          (*iter).MoveVehicle();

          vehicles_distances_[(*iter).get_vec_vehicle_position().y] = (*iter).get_id_vehicle();

     }

}

Cosa c'è di sbagliato in questo?

Modifica:

Ho cercato di usare carta :: Clear (); come un sostituto per mappare :: erase (); ma lo stesso problema si verifica!

Modifica:

Credo che ho capito ... Un filo sta cercando di fare un uso del vehicles_distances_ mentre è cancellato .. (?)

Modifica:

Problema risolto! Così era venuta dalla mappa :: erase (); come previsto. i bypassato il problema creando un'altra variabile map dove la coppia <key, value> stata invertita in modo da posso aggiornare la mappa. (Dal momento che la chiave che ho bisogno è la distanza, e la distanza non è unico in quanto cambia ogni volta ma l'id_vehicle è unico!). Alla fine ho appena preso quella mappa, invertito nuovamente la <key, value> e trasferito alla mappa originale che può essere dichiarato nuovamente in ogni ciclo ...

Grazie a tutti!

È stato utile?

Soluzione

In primo luogo, per l'amore di tutto ciò che è, bene, amabile, non utilizzare Dev-C ++ . Vorrei sapere come la gente continua a correre in quel pezzo di spazzatura. Non è stato mantenuto per anni , e anche quando è stato mantenuto, era ancora un pezzo buggy di spazzatura che mancava di funzionalità di base. Fosso, e andare per una delle innumerevoli alternative più liberi.

Ora, sulla vostra domanda: qualcosa di casuale, perché avete fatto il vostro programma segfaults illegale in precedenza. Non farlo. ;)

se il programma scrive fuori limite da qualche parte, qualsiasi cosa potrebbe accadere. Si potrebbe colpire una pagina non allocato, nel qual caso si ottiene un segfault. Oppure potrebbe colpire i dati non utilizzati in una pagina che viene assegnato al vostro processo, nel qual caso non avrà alcun effetto pratico (a meno che non è correttamente inizializzata successivamente, sovrascrivendo il vostro primo, illegale, scrivere e si quindi provare a leggere da esso , aspettandosi il valore originale (non valido) di essere ancora lì. Oppure potrebbe colpire i dati che in realtà è in uso, nel qual caso si otterrà gli errori più tardi, quando il programma tenta di leggere i dati.

Praticamente gli stessi scenari esistono nella lettura dei dati. Si può essere fortunati e ottenere immediatamente un segfault, o si può colpire la memoria non utilizzata e non inizializzato, e leggere i dati garbage out (che molto probabilmente causare un errore più tardi, quando si utilizza i dati), oppure si può leggere da indirizzi di memoria che sono già in uso (che vi darà anche spazzatura).

Quindi sì, questi errori sono difficili da trovare. Il miglior consiglio che posso dare è quello di 1) cospargere afferma su tutto il codice per garantire invarianti di base sono mantenute, e 2) dopo passo attraverso il programma, e ad ogni passo, verificare che non si sta leggendo o scrivendo agli indirizzi che don' t appartengono a voi.

MSVC ha un sicuro opzione SCL abilitata di default che eseguirà controllo dei limiti sul codice STL, che può aiutare avvistare gli errori come questo.

Credo che il GCC ha un'opzione per fare qualcosa di simile (ma non è abilitato di default).

segfaults sono brutte. Una volta che le persone sono state morsi da un errore come questo un paio di volte, tendono a diventare molto più disciplinato con evitando l'accesso alla memoria fuori dai limiti. :)

Altri suggerimenti

Si potrebbe provare a Valgrind come un modo per aiutare a trovare il problema. Data la linea che hai messo in questione, avrei dovuto intuire che hai sia corrotto il mucchio, o avete un problema di stack.

La domanda ovvia sarebbe "ciò che è _p". Nel debugger si dovrebbe essere in grado di guardare lo stack di chiamate. Seguire _p torna alla sua origine. Confermare la sua dimensione corretta, che non è stato eliminato, e che in effetti esiste.

Se questo non è facile, c'è sempre i metodi di forza bruta di commentando (sospetta) codice casuale fino a quando non funziona o andando indietro e diffing contro una nota, copia di lavoro.

Questo è incredibilmente vago, quindi è quasi impossibile rispondere. Un suggerimento ovvia sarebbe quella di verificare se si sta inizializzare tutte le variabili. Alcuni compilatori azzerare la tua roba non inizializzato in di debug e non fare che in rilascio, per esempio, che porta a risultati casuali e inaspettati.

È possibile utilizzare _CrtSetDbgFlag() al all'inizio del programma per attivare alcune opzioni mucchio di debug. Vedi anche Il CRT Debug Heap . Questo può aiutare a rintracciare dove si sta facendo cose cattive con la memoria. E 'disponibile in runtime C di Microsoft, che i collegamenti del compilatore MinGW contro per impostazione predefinita. Se stai usando invece runtime C di GNU, allora non sarà in grado di seguire questa strada.

Il problema è molto più probabile che sia nel codice che in stl_construct.h. Sto assumendo che il file è parte della distribuzione STL per Dev-C ++. L'errore di segmentazione può essere accadendo in codice che è stato un'istanza utilizzando i modelli in stl_construct.h, ma la causa principale del problema sta per essere altrove. Vorrei provare a risolvere questo problema ottenendo l'analisi dello stack al momento della caduta. Per ogni funzione nella traccia dello stack (soprattutto quelle che sono state recentemente scritte), cercare di esaminare il codice e cercare i seguenti tipi di possibili errori:

  • variabili non inizializzate (specialmente indici utilizzati per l'accesso matrice)
  • Memoria usata dopo che è stato liberato o cancellato.
  • accesso Array fuori dei limiti della matrice
  • L'allocazione di memoria che viene utilizzato senza essere controllato per NULL (non è un problema se si utilizza di nuovo perché che non restituisce NULL, viene generata un'eccezione)

La tua descrizione, e lo stack di chiamate, suggeriscono che il programma si blocca durante l'inizializzazione delle variabili statiche. Questo è un errore comune di C ++. Non v'è alcun modo semplice per controllare l'ordine di inizializzazione per le variabili statiche

Ad esempio, il programma può avere foo oggetto che dipende oggetto bar; ma può essere che il programma sta chiamando il costruttore per foo prima che costruisce bar. Questo sarebbe male, e potrebbe causare il tipo di problema si sta descrivendo. (È CheckingInstructionsThread una variabile statica che genera un filo? Questo potrebbe essere il problema proprio lì.)

Per risolvere questo problema, si potrebbe aver bisogno di guardare attraverso i file cpp del vostro programma per le variabili statiche (tra cui la statica di classe e globali), in particolare quelli che sono di un certo tipo di classe. Si può o non può contribuire a modificare le costruttori di scrivere alcune tracce a stderr; utilizzare fprintf piuttosto che cerr se farlo.

Modifica : Se non siete sicuri se ha qualcosa a che fare con la statica, prova a mettere una riga come questa all'inizio del main():

 fprintf(stderr, "main() entered\n");

Ciò non esclude inizializzazione statico come la causa del problema; anche se non lo fa strutture incidente prima main(), si poteva ancora avere dei dati in fase di realizzazione in modo non corretto. Ma, se non si arriva alla fprintf, allora si so che l'inizializzazione statico è la causa.

che cosa fa l'analisi dello stack dirvi dopo l'esecuzione del debugger con il file core? eseguire gdb modo normale gdb a.out

quindi esaminare il file core

  

nucleo a.out.core

E uno sguardo al camino

  

BT

Questa è molto probabilmente legato alla iteratore invalidato - cercare luoghi dove si un'iterazione su recipienti e / o tengono iteratori in contenitori e rimuovere / inserire gli elementi allo stesso tempo
E come tutti gli altri ha osservato -. Utilizzare un call- impilare per trovare il punto esatto.

La prima cosa che si deve fare quando si finisce in codice che è stato testato a fondo, che non è tuo sta salendo lo stack di chiamate fino a quando si finisce nel proprio codice, dove potrete trovare le informazioni che ha causato questo problema per accadere.

Nella chiamata impilare il luogo più importante da cercare è a vostro codice (il chiamante) ed i parametri passati alla funzione che si chiama (il chiamato).

Senza queste informazioni, non possiamo aiutare di più. ; -)

Ulteriori informazioni su difetti di segmentazione: http://en.wikipedia.org/wiki/Segmentation_fault
(Lettura obbligata, puoi anche consultare i link in "Vedi anche" e "Collegamenti esterni")

Le mappe non sono molto infilare amichevole. Se si eseguono le operazioni di mappa nel codice discussione si ha realmente bisogno per bloccare tutti gli accessi a quella mappa e realizzare qualsiasi iteratori si può detenere potrebbe essere invalidata.

Si presenta come una funzione pericolosa:)

Una cosa mi striked però. Da dove viene la memoria allocata andare? Intuitivamente Mi piacerebbe avere un puntatore a un puntatore come primo argomento e poi dereferenziarlo. In questo modo:

template<typename _T1, typename _T2>
    inline void
    _Construct(_T1** __p, const _T2& __value)
    {

       ::new(static_cast<void*>(*__p)) _T1(__value);
    }

In alternativa, un riferimento a un puntatore:

template<typename _T1, typename _T2>
    inline void
    _Construct(_T1*& __p, const _T2& __value)
    {

       ::new(static_cast<void*>(__p)) _T1(__value);
    }

Il debugger dovrebbe lasciarti andare lo stack di chiamate. In questo modo si dovrebbe essere in grado di vedere il posto nel proprio codice che sta causando il guasto seg.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top