2015-02-17 9 views
7

La persona Java qui si è bloccata facendo qualche C++. Sto rilevando un'eccezione e sto provando a diagnosticare da dove proviene (purtroppo l'eccezione non viene generata quando viene eseguita tramite gdb). Tuttavia, quando stampo il what() dell'eccezione, ottengo semplicemente la stringa "std :: exception". Questo è specifico per qualsiasi cosa nella libreria standard o molte eccezioni standard restituiscono questo? Ecco quello che sto facendo per la stampa:std :: exception's what() restituisce "std :: exception"

} catch (const std::exception & ex) { 
     std::cout << ex.what() << std::endl; 
    } 

L'uscita è solo:

std::exception 

Inoltre, sto lavorando in una abbastanza grande base di codice, è possibile che questo viene da qualche eccezione sulla nostra fine, ma devo ancora trovarla attraverso le normali tecniche di ricerca, quindi attualmente mi sto orientando verso ciò che proviene dalle librerie standard.

Sto usando g ++ 4.8 se questo è rilevante.

+0

Hai un core dump che puoi caricare in gdb e fare un backtrace? –

+0

Dove viene lanciata l'eccezione? Come viene lanciato? Quale eccezione viene lanciata? Crea un [Esempio minimo, completo e verificabile] (http://stackoverflow.com/help/mcve) e mostraci. –

+0

Ciò sembra insolito per un'eccezione della libreria GCC - Mi aspetto una classe derivata più specifica come 'std :: runtime_error',' std :: length_error' ecc. (Uno di [questi] (http: //en.cppreference. com/w/cpp/error/exception)) con '.what()' che lo comunica. Penso che questo sia probabilmente dal tuo codice base. Potrebbe non esserti d'aiuto, ma se fossi in te, proverei un grep ricorsivo per ''throw \ s + std :: exception'' nel tuo codice, e se non viene visualizzato nulla puoi provare GCC intestazioni. –

risposta

3

Le eccezioni C++ sono completamente diverse dalle eccezioni Java.

Il C++ standard specifica che la stringa restituita da ciò che() è del tutto arbitrario, e l'implementazione definita:

virtual const char* what() const noexcept; 

Returns: An implementation-defined ntbs. 
Remarks: The message may be a null-terminated multibyte string 
(17.5.2.1.4.2), suitable for conversion 
and display as a wstring (21.3, 22.4.1.4). The return value remains 
valid until the exception object 
from which it is obtained is destroyed or a non-const member 
function of the exception object is called. 

Il valore di ritorno che stai ricevendo, "std :: eccezione" è perfettamente compatibile con lo standard C++.

Non fare affidamento su eccezioni C++ per dirti esattamente da dove sono state gettate dopo averle catturate, come fa Java. Questo è al di fuori dello scopo dello standard C++. In C++, un'eccezione non è altro che un meccanismo per il trasferimento del flusso di controllo dell'esecuzione.

Detto questo: molte implementazioni in C++ vi forniranno alcuni meccanismi specifici per l'implementazione per scaricare lo stack backtrace corrente, al meglio delle capacità della libreria di runtime. Controlla la documentazione del compilatore C++ per maggiori informazioni.

gcc, ad esempio, offre backtrace(), insieme ad alcune funzioni interne gcc per convertire gli indirizzi grezzi restituiti da backtrace() in simboli e altre funzioni per rendere invisibili i simboli. Usando ciò, è possibile inventare un analogo analogo alla gestione delle eccezioni di Java; anche se l'implementazione di gcc non è perfetta e presenta alcuni buchi funzionali e richiede anche una pianificazione anticipata e classi di eccezioni personalizzate i cui costruttori acquisiscono il frame dello stack corrente (prima dello l'eccezione viene effettivamente generata); e, una volta rilevata, l'istanza della classe di eccezioni generata può essere ispezionata per le informazioni di backtrace acquisite.

Ma ciò non aiuta realmente la situazione attuale. Suggerirei di controllare la documentazione del compilatore C++, come suggerito, e anche di esaminare le capacità del debugger. Un debugger C++ dovrebbe consentire di impostare un punto di interruzione quando vengono lanciate eventuali eccezioni e prima che vengano rilevate, in modo da poter esaminare lo stack backtrace tramite il debugger, quando si verifica l'eccezione.

+0

Grazie, darò un'occhiata al backtrace. Questo potrebbe salvarmi dal fare una ricerca binaria attraverso l'intera base di codice! – Pace

+0

backtrace ha aiutato (non è mai stato possibile risolvere correttamente i simboli ma sono riuscito a salvarli e in seguito li ho inviati in gdb per ottenere le posizioni) e sono stato in grado di incappare nella radice del problema. Grazie. – Pace

+0

Questa risposta fa sembrare che i messaggi di eccezione siano generalmente definiti dall'implementazione in C++, ma questo si applica solo alla classe di base 'std :: exception' e non a classi derivate come' std :: runtime_error', dove 'what' is garantito per restituire la stringa che hai passato nel costruttore. Ad esempio, §22.2.7/3 dice: * "Postconditions:' strcmp (what(), what_arg.c_str()) == 0' * ". IOW, se creo 'std :: runtime_error x (" pippo ")', allora 'cosa' non deve restituire' "std :: exception" '. –

10

Questo potrebbe essere a causa di due cose:

  1. Qualcuno si limita a throw std::exception() da qualche parte, che non è molto utile.

  2. Una classe derivata da std::exception viene copiata in std::exception. Questo è un problema chiamato Object Slicing.

Ho appena commesso il secondo errore. Ho avuto questo codice:

try 
{ 
    // Some Boost stuff 
} 
catch (std::exception e) 
{ 
    cerr << e.what() << endl; 
} 

È necessario assicurarsi di fare std::exception& e. So che non hai commesso questo errore, ma è possibile che qualcun altro l'abbia fatto all'interno del codice (o qualcuno che viene da Google).

+2

Grazie, mi mancava il &. – Tuntable

Problemi correlati