Domanda

Ho una classe con un metodo statico che assomiglia approssimativamente a:

class X {
    static float getFloat(MyBase& obj) {
        return obj.value();  // MyBase::value() is virtual
    }
};

Lo sto chiamando con un'istanza di MyDerived che subclasse MyBase:

MyDerived d;
float f = X::getFloat(d);

Se collego il file obj contenente X nel mio eseguibile, tutto funziona come previsto. Se mi aspetto di ottenere 3.14, ottengo.

Se creo un .lib che contiene il file X.obj e il collegamento in .lib, si rompe. Quando chiamo getFloat (), restituisce -1. # IND00 . È un qualche tipo di valore sentinella che dovrebbe dirmi cosa c'è che non va qui?

C'è qualcosa di diverso quando si collega in una lib piuttosto che in un obj direttamente?

Non visualizzo avvisi o errori del compilatore.

Modifica
Sto usando Visual Studio 2005 su Windows XP Pro SP3. Per essere sicuro di non collegare vecchi file, ho clonato il metodo value () in un nuovo metodo value2 () e l'ho chiamato invece. Il comportamento era lo stesso.

Modifica n. 2:
Quindi, se seguo la chiamata con il mio debugger, sto scoprendo che non sta andando nel mio metodo value (). Invece sta andando in un metodo diverso (non correlato). Questo mi fa pensare che la mia vtable sia corrotta. Penso che il comportamento che sto vedendo debba essere un effetto collaterale di qualche altro problema.


Risolto! (grazie a Vlad)
Si scopre che stavo violando la sola regola di definizione (ODR) anche se non era evidente dal codice che ho pubblicato. Questo è un ottimo articolo dei ragazzi di Visual C ++ che spiega il problema e un modo per rintracciarlo. Il flag del compilatore / d1reportSingleClassLayout è un fantastico strumento di apprendimento.

Quando ho scaricato il layout della mia classe per MyBase e MyDerived nei due diversi progetti, ho trovato differenze tra il codice chiamante e il codice della libreria. Si scopre che avevo alcuni blocchi #ifdef nei miei file di intestazione e la corrispondente istruzione #define era nell'intestazione precompilata per il progetto principale ma non nel sottoprogetto (la libreria ). Ho già menzionato quanto male penso siano le macro del preprocessore?

In ogni caso, sto solo pubblicando queste cose perché potrebbero essere utili a qualcun altro. Questa domanda è stata anche molto utile per me.

È stato utile?

Soluzione

Questo problema si verifica quando la lib e l'eseguibile sono stati compilati con diverse definizioni della classe MyDerived (ovvero versioni diverse di .h /.hh/.hpp che dichiara MyDerived . Pulisci e ricostruisci completamente i tuoi progetti. A parte questo, diverse opzioni del compilatore potrebbe essere responsabile, sebbene sia alquanto improbabile.

Se il problema persiste dopo aver ricostruito tutto da zero, quindi risolverlo istanziando un oggetto fittizio MyDerived all'interno di getFloat , nella libreria. Utilizzare il debugger per confrontare il vtable del fittizio MyDerived (istanziato nella libreria) e il vtable del MyDerived riferimento all'oggetto passato come parametro (istanziato nell'eseguibile.) Qualcosa dovrebbe essere subito visibile.

Altri suggerimenti

Dato che una lib è solo un contenitore, se si collega lo stesso file .obj in entrambi i casi, come dice Brian, non dovrebbero (non è possibile?) fare la differenza.

Una cosa da guardare è che se hai cambiato la definizione di MyBase devi ovviamente ricompilare sia la libreria che il codice che la utilizza. Ad esempio, se hai aggiunto un nuovo metodo virtuale a MyBase prima del metodo value, ciò rovinerebbe la libreria poiché l'offset v-table del valore sarebbe diverso.

Non ci dovrebbero essere differenze. Assicurati solo che i file .h che stai includendo corrispondano al .lib che stai collegando esattamente. Sospetto che tu stia collegando a un vecchio file .lib.

Se stai usando Visual Studio, invece di specificare esplicitamente il file .lib, fai semplicemente clic con il pulsante destro del mouse sul progetto e imposta le dipendenze per il progetto .lib. In questo modo sarai sicuro che utilizza il file .lib corretto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top