Domanda

Sto lavorando al porting di un'applicazione Visual C++ su GCC (dovrebbe basarsi su MingW e Linux).

Il codice esistente utilizza __try { ... } __except(1) { ... } si blocca in alcuni punti in modo che quasi nulla (a parte forse errori di tipo memoria insufficiente?) possa far uscire il programma senza eseguire una registrazione minima.

Quali sono le opzioni per fare qualcosa di simile con GCC?

Modificare:Grazie per il puntatore alle opzioni /EH in Visual Studio, ciò di cui ho bisogno ora sono alcuni esempi su come gestire i segnali su Linux.ho trovato questo messaggio dal 2002.

Quali altri segnali oltre a questo? SIGFPE E SIGSEVG devo stare attento?(Per lo più si preoccupano di quelli da cui potrebbero essere cresciuti Me fare qualcosa di sbagliato)

Informazioni sulle taglie:Voglio che la mia applicazione sia in grado di registrare automaticamente il maggior numero possibile di condizioni di errore prima di uscire.

Quali segnali potrei ricevere e dopo quali sarebbe generalmente impossibile registrare un messaggio di errore?(Memoria esaurita, cos'altro?)

Come posso gestire le eccezioni e (soprattutto) segnalare in modo portabile che il codice almeno funzioni allo stesso modo su Linux e MingW.#ifdef va bene.

Il motivo per cui non ho solo un processo wrapper che registra l'errore è che per motivi di prestazioni risparmio la scrittura di alcuni dati su disco fino all'ultimo minuto, quindi se qualcosa va storto voglio fare tutti i tentativi possibili per scrivere i dati prima uscendo.

È stato utile?

Soluzione

try { xxx } catch(...) { xxx } sarebbe più portabile ma potrebbe non catturare tanto.Dipende dalle impostazioni e dagli ambienti del compilatore.

Utilizzando le impostazioni VC++ predefinite, gli errori asincroni (SEH) non vengono recapitati all'infrastruttura EH C++;per catturarli è necessario utilizzare invece i gestori SEH (__try/__Exception).VC++ consente di instradare gli errori SEH tramite la gestione degli errori C++, che consente a catch(...) di intercettare gli errori SEH;questo include errori di memoria come dereferenziamenti di puntatori nulli. Dettagli.

Su Linux, tuttavia, molti degli errori per i quali Windows utilizza SEH vengono indicati tramite segnali.Questi non vengono mai catturati da try/catch;per gestirli è necessario un gestore di segnale.

Altri suggerimenti

Perché non utilizzare le eccezioni standard C++ invece dell'estensione proprietaria di MSFT?C++ ha un concetto di gestione delle eccezioni.

struct my_exception_type : public logic_error {
    my_exception_type(char const* msg) : logic_error(msg) { }
};

try {
    throw my_exception_type("An error occurred");
} catch (my_exception_type& ex) {
    cerr << ex.what << endl;
}

C++ ha anche una clausola "catchall", quindi se vuoi registrare le eccezioni puoi utilizzare il seguente wrapper:

try {
    // …
}
catch (...) {
}

Tuttavia, questo non è molto efficiente in C++ perché la creazione di un wrapper generale di questo tipo significa che è necessario inserire il codice di gestione ogni stack frame successivo da parte del compilatore (a differenza dei sistemi gestiti come .NET in cui la gestione delle eccezioni non comporta costi aggiuntivi purché non venga effettivamente generata alcuna eccezione).

Per motivi di portabilità, una cosa da provare è utilizzare i blocchi try-catch per la maggior parte delle eccezioni vanilla e quindi impostare un gestore di terminazione (set_terminate_handler) per avere un hook minimo disponibile per condizioni di uscita catastrofiche.Puoi anche provare ad aggiungere qualcosa come un gestore atexit o on_exit.Il tuo ambiente di esecuzione potrebbe essere bizzarro o corrotto quando accedi a queste funzioni, ovviamente, quindi fai attenzione a quanto presumi un ambiente sano.

Infine, quando si utilizzano coppie try-catch regolari, è possibile considerare l'utilizzo dei blocchi try di funzioni invece dell'apertura di un blocco try nel corpo di una funzione:

int foo(int x) try {
  // body of foo
} catch (...) {
   // be careful what's done here!
}

sono una parte relativamente sconosciuta di C++ e in alcuni casi possono offrire il ripristino anche in caso di corruzione parziale dello stack (su piccola scala).

Infine, sì, probabilmente vorrai indagare su quali segnali puoi gestire in modo continuativo da solo o su quali potresti interrompere, e se desideri meno meccanismi di gestione in atto, potresti considerare di chiamare la versione non-throwing del new operatore e compilando per non generare eccezioni in virgola mobile, se necessario (puoi sempre controllare isnan(.), isfinite(.), sui risultati FP per proteggerti).

Su quest'ultima nota, fai attenzione:Ho notato che le funzioni di classificazione dei risultati in virgola mobile possono trovarsi in intestazioni diverse sotto Linux e Windows...quindi potrebbe essere necessario condizionalizzare tali inclusioni.

Se ti senti malizioso, scrivi tutto usando setjmp e longjmp (è uno scherzo...).

Catturare le eccezioni C++ con catch(...) ti mette già in una zona crepuscolare.

Cercando di individuare gli errori non rilevati da catch(...) ti colloca esattamente all'interno di un comportamento indefinito.Non è garantito che il codice C++ funzioni.Il tuo codice di registrazione minimo potrebbe invece causare il lancio del missile.

Il mio consiglio è di non provarci nemmeno catch(...).Rileva solo le eccezioni che puoi registrare in modo significativo e sicuro e lascia che il sistema operativo gestisca il resto, se presente.

Il debug post-mortem diventa brutto se si verificano errori nella gestione degli errori di codice oltre alla causa principale.

Un modo facile da usare, portatile e che utilizza a malapena le risorse sarebbe quello di catturare le classi vuote.So che all'inizio può sembrare strano, ma può essere molto utile.

Ecco un esempio che ho fatto per un'altra domanda che vale anche per la tua domanda: collegamento

Inoltre, puoi avere più di 1 cattura:

try
{
   /* code that may throw exceptions */
}
catch (Error1 e1)
{
   /* code if Error1 is thrown */
}
catch (Error2 e2)
{
   /* code if Error2 is thrown */
}
catch (...)
{
   /* any exception that was not expected will be caught here */
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top