Ho un'applicazione per Linux C++ e vorrei testare un puntatore a oggetti per la validità prima di dereferenziarlo. Tuttavia, try/catch non funziona su Linux per colpa della segmentazione. Come si può fare?Provare/Catturare un errore di segmentazione su Linux
risposta
Se si dispone di uno scenario in cui molti puntatori all'interno della propria app fanno riferimento agli stessi oggetti a durata limitata, una soluzione popolare è utilizzare boost smart pointers. Edit: in C++ 11, entrambi questi tipi sono disponibili nella libreria standard
Si consiglia di utilizzare shared_ptr
per puntatore (s) che sono responsabili per tutta la durata del vostro oggetto e weak_ptr
per gli altri puntatori , che potrebbe diventare non valido. Vedrai che weak_ptr
ha il controllo di validità che stai richiedendo integrato.
Inizializza il puntatore su NULL. Se dopo qualche elaborazione è ancora NULL non è valido, altrimenti è valido.
Se elimino un oggetto che sia il puntatore non è NULL ma punta alla memoria non valida. Come posso convalidare tale puntatore? – jackhab
Perché diavolo vorresti? L'hai cancellato. Se stai usando i puntatori ovunque e non sei sicuro che siano eliminati o no, stai facendo qualcosa di MOLTO sbagliato. – Bombe
Secondo. I puntatori non validi sono indicatori non validi. In seguito, la variabile puntatore non è più accessibile o lo imposti a 0. Oppure, dato che questo è C++, scopri RAII. – gimpf
È possibile abilitare un gestore di segnale per SIGSEGV per questa occorrenza. Vedi la pagina man "segnale" per i dettagli. L'altra alternativa è usare riferimenti che sono garantiti come validi. Dipende dalla tua applicazione, naturalmente.
La pagina man dice che lo stato del processo non è definito se ignora SIGSEGV. Posso riprendere l'applicazione C++ dopo aver catturato SIGSEGV? – jackhab
Buona domanda, probabilmente non sicura. Penso che sia generalmente meglio usare riferimenti anziché puntatori se sei preoccupato per la validità. Come hanno sottolineato gli altri utenti, puoi registrare dove si verifica l'errore e correggerlo. –
Anche i riferimenti non sono garantiti come validi. Se la durata dell'oggetto referenziato termina prima dell'uso del riferimento, anche i risultati sono indefiniti (in pratica identici a un puntatore non valido). I riferimenti non possono essere inizializzati su null e non resettati. Questo è tutto. – gimpf
Un errore di segmentazione non è un'eccezione (come NullPointerException di Java); è un segnale inviato dal sistema operativo al processo. Dai un'occhiata a the manpage for sigaction per i puntatori su come installare un gestore per l'errore di segmentazione (SIGSEGV).
Come si verifica il puntatore per la validità? Confronta con NULL?
La cosa migliore da fare è eseguire il programma in Valgrind. Un bug potrebbe essere in un posto abbastanza diverso.
Aggiornamento: Sulla piattaforma Win32 c'è qualcosa come __try __except che consente di rilevare alcune eccezioni. Per quanto ne so, non esiste un equivalente Linux per quella funzionalità di Win32.
Su Windows è possibile rilevare un'eccezione quando si accede a un puntatore all'oggetto deallocato e si può affrontare la situazione.In Linux si ottiene SIGSEGV. La mia domanda è un modo per convalidare un puntatore che una volta puntava a un oggetto e quindi non è NULL ma ancora invalidato dall'operatore delete. – jackhab
Non sono un esperto di Win32 ma una volta ho usato __try __eccetto per tali cose. –
Queste sono solo le cose di Windows, esponendo l'eccezione Strutturata della piattaforma gestione "(SEH) in C++. L'equivalente linux è segnali ... ma penso che il suggerimento di Shmoopty di shared_ptr/weak_ptr sia più lungo la linea giusta. – timday
Se si collega un gestore al SIGSEGV, non c'è molto che si possa fare oltre a registrare il fatto che l'errore si è verificato e fallire con garbo. Il tuo programma si trova in uno stato indefinito quando si verifica questa violazione e quindi potrebbe non essere sicuro continuare il normale funzionamento.
Oltre il controllo per NULL, non credo ci sia un modo per verificare se un puntatore è "valido" nel senso che stai descrivendo. Durante il normale funzionamento, errori come questo non dovrebbero accadere in quanto rappresentano un bug, quindi dovresti volere che il tuo programma fallisca, anche se con grazia.
I puntatori sono memorizzati in oggetti. Sono inizializzati nel costruttore, potenzialmente su 0 (NULL). Vengono eliminati nel distruttore, possibilmente in assegnazione e raramente in altre funzioni. Quando vengono eliminati in membri diversi dal distruttore, viene immediatamente assegnato un nuovo valore o 0.
Non esiste un modo naturale e universale con puntatori C++ non elaborati. C++ presuppone che traccerai quell'informazione.
Nella maggior parte dei casi, è possibile gestirlo ricordando di impostare i puntatori su NULL quando non sono validi. I nuovi puntatori che inizialmente non puntano dovrebbero essere impostati su NULL e gli oggetti appena eliminati dovrebbero avere i loro puntatori impostati su NULL.
In generale, per quanto riguarda l'idea piuttosto strano di "controllare un puntatore non NULL per la validità", uno sguardo a questo articolo: http://blogs.msdn.com/oldnewthing/archive/2006/09/27/773741.aspx ("IsBadXxxPtr in realtà dovrebbe essere chiamato CrashProgramRandomly")
- 1. Un errore di segmentazione Python?
- 2. Perché sto ricevendo un errore di segmentazione?
- 3. Un semplice programma di memoria condivisa C++ scritto su linux: errore di segmentazione
- 4. Errore di segmentazione Sprintf
- 5. Compilazione incrociata ARM, errore di segmentazione su ereditarietà multipla
- 6. pthread (errore di segmentazione)
- 7. Errore di segmentazione C++
- 8. errore di segmentazione: 11
- 9. Nmap :: Parser, errore di segmentazione su file di grandi dimensioni
- 10. Linux: gestione di un errore di segmentazione e acquisizione di un core dump
- 11. Errore di segmentazione (core scaricato)
- 12. Errore di segmentazione in PHP?
- 13. matrice 2D Grande dà errore di segmentazione
- 14. Errore di segmentazione Git: 11
- 15. errore di segmentazione con strcpy
- 16. Errore di segmentazione di tipo ctypes Python
- 17. errore di segmentazione utilizzando scanf
- 18. Errore di segmentazione MPI in MPI_Isend()
- 19. errore di segmentazione per inet_ntoa
- 20. Errore di segmentazione in Realloc
- 21. Segnale 11, errore di segmentazione su iphone App exit
- 22. CoreDumpDirectory non funziona su ubuntu; errore di segmentazione con php
- 23. errore quando `` tar` un .zip` su Linux
- 24. GHC: errore di segmentazione in condizioni strane
- 25. Come eseguire il debug di un errore di segmentazione Python?
- 26. Dichiarazione di causa variabile errore di segmentazione
- 27. Errore di segmentazione: 0x0000000000000001 in ??() cercando di compilare/link sotto Linux
- 28. errore di segmentazione haskell con fattoriale
- 29. Esecuzione di printf() e errore di segmentazione
- 30. Errore di segmentazione: 11 in SVN checkout
Non ho usato shared_prt ma per quanto ho capito è un puntatore che controlla la vita di un oggetto Ho una situazione opposta Ho un oggetto che può cancellare se stesso dopo aver ricevuto un messaggio Ho bisogno di quelli che lo indicano per avere un modo per sapere che possiedono s puntatore non valido. – jackhab
Questo è esattamente il tipo di caso in cui è stato creato weak_ptr. Weak_ptr lascerà morire l'oggetto e segnalerà l'invalidità se in seguito tenterai di accedere all'oggetto tramite weak_ptr. Una soluzione decisamente migliore rispetto a SIGSEGV! – timday
Questo è quello che pensavo fosse la tua situazione. Il messaggio "delete me" dovrebbe resettare il solo_un_padrone condiviso. Dopodiché, tutti i weak_ptr creati da that shared_ptr sapranno che non sono validi. Dai un'occhiata al link weak_ptr per gli esempi. –