2013-11-20 17 views
6

Ho una grande app Mac che funziona per un paio di giorni alla volta su un grande set di dati. È un mix di Objective-C++ e C++. Funziona alla grande su Mountain Lion, ma su Mavericks, dopo aver corso per circa 10 o 20 minuti (in cui un paio di milioni di oggetti sono assegnati e distrutti), si blocca. Si comporta come se si bloccasse con un puntatore non valido (ad esempio chiamando una funzione su un oggetto C++ cancellato), ma l'oggetto a cui punta è in uno stato che non ha assolutamente senso.Arresto anomalo di C++ e Objective-C++ su Mavericks

Tutte le mie classi C++ ereditare da una classe base comune in cui il costruttore simile a questa:

MyClass::MyClass() 
{ 
    mCreated = 12345; //int member variable set here and NEVER TOUCHED AGAIN. 
    //other initialization stuff 
} 

Quando si blocca, il debugger mostra che nell'oggetto male, il valore per mCreated è 0. E ' comportandosi come se l'oggetto non avesse mai eseguito il suo costruttore!

Non penso che stomping della memoria, perché questo valore non è mai diverso da 0 o il valore previsto, e nessuno degli altri campi nell'oggetto ha valori che assomigliano alla spazzatura che ci si aspetterebbe dalla memoria stomping .

Ho anche provato a scattare con lo scarabocchio attivato e i valori 0x555 e 0xaaa non vengono visualizzati da nessuna parte. Ho anche provato i bordi di guardia.

L'indagine approfondita non ha rivelato nulla. L'oggetto cattivo non è nemmeno sempre la stessa classe. Tutto quello che riesco a pensare è che qualcosa con la nuova memoria in Mavericks (comprimere memoria inutilizzata) sta causando qualche nuovo comportamento (forse un bug o forse qualche regola precedentemente sconosciuta, per lo più non applicata che ora conta davvero).

Qualcuno ha visto qualcosa di simile? O qualcuno sa di regole di memoria per lo più sconosciute che si applicherebbero più fortemente sotto Mavericks?

+0

recentemente imparato ** molto utile ** tecnica di debug (quindi mi sento meglio condividerla): GDB (e sicuramente LLDB) può guardare gli indirizzi di memoria da leggere/scrivere su. Non ricordo il comando esatto, ma lo troverai sicuramente, cerca "gdb watch memory access". –

+1

aw wait, no, [eccolo qui] (http: // stackoverflow.com/domande/58851/can-i-set-a-punto di interruzione-on-memory-access-in-gdb/59146 # 59146). –

+0

@ H2CO3 - Buono a sapersi, ma non c'è modo di sapere quale indirizzo sarà soffocato. –

risposta

4

Penso che tu abbia ragione riguardo al sospetto di puntatore non valido. Potrebbe essere un puntatore a un oggetto eliminato o potrebbe essere un puntatore di dati inutili. O uno sarebbe coerente con il membro mCreated diverso da quello che ci si aspetta. Nel caso di un oggetto eliminato, la memoria potrebbe essere utilizzata per qualcos'altro e quindi impostata su un altro valore. Nel caso di un garbage pointer, non stai puntando a qualcosa che sia mai stato un'istanza della tua classe.

Non so quanto bene lo strumento di allocazione funzioni per oggetti C++, ma potresti provare a riprodurre l'arresto al di sotto di questo. Quando si ferma nel debugger, prendi il puntatore this e poi recupera la cronologia di quell'indirizzo da Strumenti.

Se Strumenti non funziona, è possibile impostare la variabile di ambiente MallocStackLoggingNoCompact. Poi, quando si ferma nel debugger, esaminare il puntatore this e utilizzare i seguenti comandi per visualizzare la cronologia di tale indirizzo:

(lldb) script import lldb.macosx.heap 
(lldb) malloc_info --stack-history 0x10010d680 

(utilizzare l'indirizzo this invece di 0x10010d680, naturalmente.)

In alternativa, è possibile utilizzare il comando malloc_history da una shell per esaminare la cronologia, se farlo all'interno di LLDB è ingombrante.

+0

Ho provato questa opzione e invocato malloc_info sull'indirizzo su cui si ferma. Non ha restituito nulla. Ho verificato di aver dato l'indirizzo giusto. L'ho provato sull'indirizzo di un altro oggetto nello stack che era in uno stato valido e ha stampato una riga su malloc, quindi uno sul nome completo della classe, quindi "error: expression failed" seguito da un po 'di roba iniziando con 'typedef int kern_return_t; typedef unsigned task_t; #define MAX_FRAMES 128' ecc. Sembra parte di un file di intestazione o qualcosa del genere. –

+0

Provare a utilizzare lo strumento "malloc_history". Sono a conoscenza ma non esperto del comando LLDB. Potrebbe avere limitazioni. I risultati che hai, tuttavia, suggeriscono che il puntatore "this' è spazzatura. Prova ad andare in cima allo stack per capire dove il chiamante ha ottenuto il puntatore dell'istanza su cui sta chiamando le funzioni membro. Forse l'ha preso da una variabile membro dell'istanza deallocato, ecc. Da qualche parte, c'è un inizio nella catena della spazzatura. –

Problemi correlati