2014-07-18 20 views
10

[Respiro profondo.] Abbiamo un'applicazione che si apre in una finestra usando WxMotif 2.6.3 (la libreria della GUI non era - e non lo è - la mia scelta). Funziona perfettamente con i sistemi ix86 a 32 bit. Ho avuto il compito di convertirlo in un'applicazione a 64 bit. È sempre segreta. Sono su RHEL 6, quindi ho compilato usando gcc 4.4.7. Dopo molti stridori di denti, il problema sembra evidente: in wxFrame :: DoCreate, m_mainWidget è impostato (correttamente); in wxFrame :: GetMainWidget, viene restituito come puntatore nullo. Il puntatore nullo provoca l'arresto anomalo. Utilizzando gdb, l'istruzione che imposta m_mainWidget èSegfault: e lo smontaggio è diverso tra objdump e gdb

mov %rax,0x1e0(%rdx) # $rdx = 0x68b2f0 

che il codice che ottiene m_mainWidget è

mov 0x1f0(%rax),%rax # $rax = 0x68b2f0 

In gdb, posso esaminare la memoria e vedere che il puntatore 0x68b4d0 sia corretto. Perché l'offset è errato?

Per confondere le cose ancora di più, quando uso objdump di smontare libwx_motifd_core-2.6.so.0.3.1, l'assemblea "get" è

mov 0x1e0(%rax),%rax 

In objdump, sia il get e l'uso insieme 0x1e0 come l'offset. Cosa sta succedendo?

Ho caricato alcune informazioni rilevanti qui: GitHub

ho incluso un piccolo programma che si riproduce il problema sul mio sistema.

Per approfondire, vedo nello smontaggio di wxFrame :: DoCreate, che ulteriori utilizzi di m_mainWidget recuperano il valore utilizzando 0x1e0 come offset (lo smontaggio è su una compilazione dove ho usato -O0, quindi il codice deve andare torna alla memoria ogni volta). "Just for Fun", ho aggiunto una nuova variabile membro a wxFrame - m_myMainWidget - e l'ho impostata subito dopo aver impostato m_mainWidget. Ho quindi avuto wxFrame :: GetMainWidget() restituire il valore locale (m_myMainWidget). Non lo sapresti: il crash si verifica ancora e GetMainWidget contiene lo stesso offset di +16 quando mi disassembro da gdb. (L'offset è non là dove io uso objdump di smontare.)

+0

Potrebbe essere questa una differenza nei livelli di ottimizzazione del compilatore? – BlackVegetable

+0

stesso comportamento se uso -O2 o -0. – John

+1

Potrebbe essere un problema di collegamento (dinamico)? – BlackBear

risposta

2

Sulla base @ commento di Igor, ho guardato i layout di classe utilizzando l'opzione -fdump-class-hierarchy compilatore. Si scopre che v'è infatti una mancata corrispondenza di layout vtable, a causa di questo blocco condizionale in include/wx/app.h:

#ifdef __WXDEBUG__ 
    virtual void OnAssert(const wxChar *file, 
          int line, 
          const wxChar *cond, 
          const wxChar *msg); 
#endif // __WXDEBUG__ 

È necessario assicurarsi che si compila il codice con la stessa impostazione __WXDEBUG__.

+0

Penso che la risposta sia qui da qualche parte. Avrei detto che entrambe le chiamate erano nella stessa unità di traduzione, ma ho semplicemente spostato la definizione della funzione per wxFrame :: GetWidget nel file ./src/motif/frame.cpp e ricompilata, e il problema sembra essere risolto. Non sono sicuro di come * qualsiasi * delle macro (come __WXDEBUG__) avrebbe potuto essere diverso da una unità di traduzione a quella successiva, dal momento che ho compilato il tutto usando ./configure; rendere; effettuare l'installazione senza cambiarlo. Grazie per l'aiuto! – John

+1

La macro non è stata definita durante la compilazione del codice, non della libreria. Il tuo 'MainApp' eredita da' wxAppConsole', ma senza 'WXDEBUG' il suo vtable manca la voce per' OnAssert' e quindi ha un layout diverso da quello che la biblioteca si aspetta (perché è stato compilato con 'WXDEBUG'). – Jester

+0

[Colpendo me stesso in testa] Che stupido da parte mia! Grazie mille. Mi hai dato un nuovo strumento da usare (-fdump-class-hierarch). – John