2009-12-08 8 views
7

Ok, quindi questo è un po 'nervosa lungo da spiegare così nudo con me ..C++: Caricamento di un file EXE come DLL, problema vftable locale

ho un exe chiamato test.exe che di solito è utilizzato come supporto applicazione sola. Voglio usare questo exe come un modulo (una DLL) all'interno di un'altra applicazione, app.exe.

Il codice in test.exe fa qualcosa di veramente semplice come:

void doTest() 
{ 
    MyClass *inst = new MyClass(); 
    inst->someMethod(); 
} 

Dove someMethod() è virtuale e MyClass ha una d'tor virtuale.
doTest() viene esportato da test.exe e quindi viene creato un lib chiamato test.lib
app.exe è collegato con questo lib per caricare staticamente test.exe all'avvio.

Quando eseguo test.exe autonomamente, funziona correttamente ma quando viene eseguito caricato da app.exe si blocca.
L'introduzione nel codice con il debugger ha rivelato che l'arresto si trova nella chiamata al metodo virtuale. Si scopre che il vftable in qualche modo va male.

Dopo alcune indagini si scopre che quando il codice all'interno del costruttore di MyClass è in esecuzione, il vftable è una cosa, ma quando la chiamata a new rendimenti è sostituirlo con qualcos'altro chiamato "vftable locale". Ho trovato this obscure discussion about why this is.

Dopo circa un giorno di debug mi è venuto in mente che i puntatori in questo "vftable locale" sono gli stessi in entrambi i casi, quando test.exe è autonomo e quando viene caricato come modulo. Questo non può essere corretto perché test.exe è caricato in un indirizzo diverso ...
Per testare questa teoria ho cambiato l'indirizzo di caricamento nelle opzioni del linker a quello in cui è caricato test.exe quando è in app.exe e ora, ecco, tutto funziona.

Ovviamente, questa non è una soluzione permanente perché la prossima volta questo indirizzo selezionato a caso potrebbe essere occupato e lo stesso problema si ripresenterà.

Quindi la mia domanda: perché questo "locale vftable" è legato all'indirizzo di caricamento statico dell'exe? sta caricando un exe come un modulo una cosa negativa? perché l'exe assume che sia caricato nel suo indirizzo statico?

Solo per il contesto: tutto questo è stato eseguito con MSVC 2008, Windows XP x64.

risposta

3

La soluzione che ho finito per utilizzare è semplicemente aggiungere una configurazione di compilazione e compilare l'exe come una vera dll invece di costringerlo a comportarsi come uno.

utilizzando /fixed:no non ha risolto il problema per qualche motivo.

Un'altra differenza I tra ex e DLL è che il punto di ingresso è diverso. il punto di ingresso di una DLL è DllMain dove un exe ha il suo punto di ingresso nel CRT che alla fine chiama main() o WinMain().

4

VC++ rimuove le informazioni di riloc da .exes di default perché normalmente non devono essere rilocabili.

È possibile forzare il mantenimento delle informazioni reloc con/fisso: no. Vedi: http://msdn.microsoft.com/en-us/library/w368ysh2.aspx

+2

L'ho provato ma non sembra avere alcun effetto per qualche motivo – shoosh