2013-03-02 19 views
6

Ho impostato un progetto in Visual Studio 2010 per scrivere test di unità su una DLL MFC esistente. Sto usando un framework di test unit testata singola e collegato al wrapper lib della DLL MFC dal progetto di test dell'unità. Sto provando a costruire una classe che prende uno std::wstring nel suo costruttore. Ecco ciò che il mio test assomiglia:Impossibile passare std :: wstring su DLL

TEST_CASE("MyProject/MyTest", "Do the test.") 
{ 
    MockDbService mockDbService; 
    Foobar foo(L"{F00DFACE-FEED-DEAD-BEEF-C0FFEEDECADE}", mockDbService); 

    foo.loadObject(); 

    REQUIRE(mockDbService.getMethodInvokeCount("query()") >= 1); 
} 

Dove Foobar è la classe esportata dalla DLL MFC in prova. Tuttavia, il framework di test riporta un'eccezione imprevista. Ho rintracciato il costruttore di copie di std::wstring quando copiavo la stringa nel costruttore di Foobar. Il debugger MSVC segnala la stringa di origine come <Bad Ptr>.

Ho creato un costruttore fittizio, Foobar::Foobar(long num, IDbService& db) e tutti i valori (incluso lo IDbService&) si presentano perfettamente.

Sia la DLL MFC che il mio test di unità EXE condividono un foglio di proprietà che dovrebbe mantenere i flag del compilatore equivalenti. Sto costruendo ed eseguendo il test in modalità di debug. Qualche idea per cui lo std::wstring non può copiare attraverso la DLL?

+2

È possibile collegare in modo dinamico sia l'EXE che la DLL con la versione di debug del CRT? ('/ MDd') –

+1

@ Mr.C64 Wow, era così. Il mio progetto di test unitario utilizzava '/ MD' e la DLL MFC era'/MDd'. Mi piacerebbe una breve spiegazione come risposta in modo che io possa capirlo; e lo accetterò. Grazie! –

+0

Ho aggiunto una breve spiegazione. Fondamentalmente, penso che il problema nel tuo caso sia che 'std :: wstring' di debug-build ha un'implementazione diversa rispetto a' std :: wstring' di release-build. –

risposta

9

Si dovrebbe verificare che sia il file EXE e DLL sono dinamicamente collegati con lo stesso di debug CRT (/MDd opzione del compilatore). Assicurarsi che anche altre impostazioni come _HAS_ITERATOR_DEBUGGING siano uguali sia per l'EXE che per la DLL.

(Una scorciatoia potrebbe essere quella di utilizzare semplicemente const wchar_t* anziché std::wstring nell'interfaccia di classe e creare semplicemente un std::wstring dal puntatore raw all'interno del corpo del costruttore).

EDIT: avete confermato che CRT non corrispondente (cioè EXE costruito con /MD vs. DLL costruito con /MDd) è stato il problema. Il fatto è che lo stesso nome di classe std::wstring indica due classi diverse nelle build di debug (/MDd) e nelle versioni di release (/MD). In effetti, nelle build di debug ci possono essere ulteriori meccanismi all'interno dell'implementazione della classe per aiutare il debugging; questa meccanica può introdurre inefficienze, quindi viene rimossa nelle versioni di rilascio. Pertanto, la struttura interna di build di debug std::wstring è diversa da std::wstring della versione di rilascio (ad esempio, se provi a stampare le istanze di std::wstring prime, puoi trovare numeri diversi nelle build di rilascio e nelle build di debug). Quindi, il file EXE creato con /MD si aspettava lo std::wstring di release-build; invece la DLL creata con /MDd si aspettava il std::wstring di debug-build: c'è una discrepanza tra queste due aspettative (un modulo si aspetta la classe X ma l'altro modulo sta dando la classe Y) e quindi si verifica un arresto anomalo.

+0

Questo ha senso. Grazie. In tal caso, il mio problema è esattamente quello che ho trovato prima: http://stackoverflow.com/questions/2322095/why-does-this-program-crash-passing-of-stdstring-between-dlls?rq=1 Ma entrambi i miei progetti sono stati creati in Debug, quindi non pensavo che fosse correlato. Secondo quello che stai dicendo, stavo usando la build di rilascio del CRT anche con i progetti di debug. Grazie ancora. –

+1

Sì, '/ MD' è il collegamento dinamico per rilasciare DLL CRT; '/ MDd' è il collegamento dinamico per eseguire il debug di DLL CRT. –

Problemi correlati