2014-10-06 12 views
6

Utilizzo Eigen nel mio software e oggi ho riscontrato un problema, causato dalla modifica del mio codice dalla creazione di una libreria statica alla libreria dinamica in Windows, utilizzando Visual Studio 2013. Il motivo di questa opzione non era correlato a Eigen.Errori di allineamento della memoria utilizzando Eigen con una libreria dinamica con Visual Studio 2013

Sto incorporando Eigen nel mio file di libreria, che a sua volta è collegato alle mie applicazioni. Come accennato prima, questa biblioteca era stata una biblioteca statica fino ad oggi; Ho appena aggiornato il mio codebase per generare un file DLL.

Dal apportare questa modifica, ora sto ottenendo il seguente messaggio di errore da Visual Studio:

The Block at -------------------- stato assegnato da routine allineate, utilizzare _aligned_free()

(che questo messaggio compaia numerose volte con indirizzi diversi di volta in volta; ho utilizzato trattini sopra, poiché non credo che gli indirizzi specifici siano rilevanti per questo problema).

scegliendo "Riprova" apre il debugger a linea 255 su Memory.h

studio visivo IntelliSense (quando non debug) suggerisce che EIGEN_ALIGN e EIGEN_HAS_MM_MALLOC sono entrambi definiti come 1, EIGEN_MALLOC_ALREADY_ALIGNED e EIGEN_HAS_POSIX_MEMALIGN sono entrambi indefinito. Di conseguenza, dovrebbe essere in esecuzione _mm_free (ptr), che (di nuovo basato su IntelliSense) è un alias per _aligned_free (a). Di conseguenza, sembra che questo codice esegua la funzione corretta, ma non lo è.

Quando cambio il codice in una libreria statica, questo problema scompare.

L'unica cosa remotamente rilevante che ho trovato da numerose ricerche su Google era un articolo da Intel Fortran Compiler che diceva che questo messaggio di errore poteva provenire da una libreria compilata in una versione precedente che viene chiamata dal codice compilato con l'ultima versione . A parte il fatto che sto usando Visual Studio C++ 2013, ho ricostruito il codice numerose volte per essere sicuro che sia stato completamente ricompilato da uno stato pulito e questo messaggio di errore permanga.

Ho scaricato l'ultimo codice dal repository mercurial (ramo predefinito), ma questo non ha risolto il problema.

Ho cercato di essere il più completo possibile. Se avete bisogno di ulteriori informazioni, fatemelo sapere.

Edit:

ulteriore contesto:

Il 'codice client' che utilizza la DLL in questo caso è Google prova; il messaggio di errore viene generato dopo aver verificato un'aspettativa, ad esempio la classe nel file DLL sta eseguendo il distruttore per pulire un oggetto temporaneo. Non sto tentando di fare cose malvagie come allocare memoria nel file DLL e quindi de-allocarlo nell'app del driver - questo è in parte il motivo per cui trovo che sia così confuso ....

+0

Sei sicuro che la DLL e il client che utilizza la DLL sono stati costruiti uguali? Sto pensando ad alta voce - ora che è separato che la DLL sta facendo mallocs e libera in un modo e il client potrebbe fare qualcos'altro. Di solito per questo motivo non è consigliabile per un client chiamare gratuitamente su un oggetto creato in una DLL. Solitamente si esportano le routine di cleanup (cioè gratuite) dalla DLL in modo che un client possa chiamare quelle invece di farlo direttamente. Lo stesso sarebbe vero per la creazione di oggetti. –

+0

@MichaelPetch Sono abbastanza sicuro che siano costruiti allo stesso modo. Certamente la DLL e la lib static sono identiche (cambio solo le impostazioni una). Inoltre, non sto chiamando gratuitamente dal client: il codice in questione è il codice di pulizia della DLL. Nel mio caso, il client è Google Test, che esegue test di unità sul codice nella libreria; il punto di interruzione viene raggiunto in un punto in cui deve essere chiamato un distruttore di matrici Eigen temporaneo. Aggiornerò la domanda e chiarirò questo a beneficio degli altri. Vedo che questo non era chiaro prima. –

risposta

2

Ho avuto questo problema esatto . Ho convertito la mia libreria statica che utilizza Eigen in una DLL e ho iniziato a ricevere questi errori durante il test dell'unità con gtest. Non essendoci alcuna soluzione, fornirò ciò che ho fatto per risolvere il problema. In sostanza, il problema è che hai creato una nuova interfaccia per la classe contenente matrici/vettori Eigen come variabili membro e quell'interfaccia crea un puntatore alla classe con le variabili membro Eigen.

In primo luogo, se si dispone di variabili membro che sono matrici o vettori Eigen, è necessario leggere this. In sintesi è necessario aggiungere

pubblico: EIGEN_MAKE_ALIGNED_OPERATOR_NEW

alle tue definizioni di classe in cui si utilizza Eigen come variabili membro. Presumibilmente riceverai anche degli avvertimenti su warning C4316: object allocated on the heap may not be aligned 16 se stai usando il compilatore di Visual Studio.

Ora, ho ancora avuto problemi dopo che ho usato il EIGEN_MAKE_ALIGNED_OPERATOR_NEW, questo era dovuto all'utilizzo di un atomico con una classe di matrice Eigen; boost::atomic<Eigen::MatrixXf> come variabile membro. Immagino che l'allineamento sia molto importante quando si garantisce l'atomicità.

Problemi correlati