2013-03-02 15 views
6

Skonfigurowałem projekt w Visual Studio 2010, aby pisać testy jednostkowe przeciwko istniejącej biblioteki DLL MFC. Używam struktury testowej jednostkowej stacji i powiązanej z biblioteką DLL MFC z projektu testu jednostkowego. Próbuję skonstruować klasę, która ma std::wstring w jego konstruktora. Oto co mój test wygląda następująco:Nie można przekazać std :: wstring całej biblioteki 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); 
} 

Gdzie Foobar jest klasa wywiezione z MFC DLL badanego. Jednak struktura testowa zgłasza nieoczekiwany wyjątek. Śledziłem to do konstruktora kopiowania std::wstring podczas kopiowania łańcucha do konstruktora Foobar. Debugger MSVC zgłasza łańcuch źródłowy jako <Bad Ptr>.

Stworzyłem fikcyjnego konstruktora, Foobar::Foobar(long num, IDbService& db) i wszystkie wartości (w tym IDbService&) są dobrze widoczne.

Zarówno biblioteka DLL MFC, jak i mój plik EXE testu jednostki udostępniają arkusz właściwości, który powinien zapewniać równoważność flag kompilatora. Buduję i przeprowadzam test w trybie debugowania. Wszelkie pomysły, dlaczego std::wstring nie można skopiować w DLL?

+2

Czy dynamicznie łączysz plik EXE i bibliotekę DLL z wersją debugowania CRT? ('/ MDd') –

+1

@ Mr.C64 Wow, to było to. Mój projekt testów jednostkowych używał '/ MD', a DLL MFC to'/MDd'. Chciałbym otrzymać krótkie wyjaśnienie jako odpowiedź, więc mogę to zrozumieć; i zaakceptuję to. Dzięki! –

+0

Dodałem krótkie wyjaśnienie. Zasadniczo uważam, że problem w twoim przypadku polega na tym, że 'std :: wstring' debug-build ma inną implementację niż' std :: wstring' release-build. –

Odpowiedz

9

Należy sprawdzić, że zarówno EXE i DLL są dynamicznie powiązane z CRT samo debugowania (/MDd opcji kompilatora). Upewnij się, że inne ustawienia, takie jak _HAS_ITERATOR_DEBUGGING, są takie same zarówno dla EXE, jak i DLL.

(Skrótem może być po prostu użycie const wchar_t* zamiast std::wstring w interfejsie klasy, i po prostu zbuduj std::wstring z surowego wskaźnika wewnątrz korpusu konstruktora).

EDIT: Potwierdziliście CRT niedopasowania (tj EXE zbudowany /MD porównaniu DLL zbudowany z /MDd) był problem. Faktem jest, że ta sama nazwa klasy std::wstring oznacza dwie różne klasy w kompilacjach debugowania (/MDd) oraz w kompilacjach wersji (/MD). W rzeczywistości w kompilacjach debugowania może być dodatkowa mechanika wewnątrz implementacji klasy, aby pomóc w debugowaniu; ta mechanika może wprowadzić nieefektywność, więc jest usuwana w wersjach rozwojowych. Tak więc wewnętrzna struktura kompilacji debugowania std::wstring różni się od wersji kompilacji wydania std::wstring (np. Jeśli spróbujesz wydrukować surowe sizeof instancji std::wstring, możesz znaleźć różne liczby w kompilacjach wydań i kompilacjach debugowania). Tak więc EXE zbudowany z /MD oczekiwał wydania-build's std::wstring; zamiast tego biblioteka DLL zbudowana pod numerem /MDd spodziewała się, że debug-build ma numer std::wstring: istnieje niedopasowanie między tymi dwoma oczekiwaniami (jeden moduł oczekuje klasy X, ale drugi moduł podaje klasę Y), co powoduje awarię.

+0

To ma sens. Dziękuję Ci. W takim przypadku mój problem jest dokładnie taki, jaki znalazłem wcześniej: http://stackoverflow.com/questions/2322095/why-does-this-program-crash-passing-of-stdstring-between-dlls?rq=1 Ale oba moje projekty zostały zbudowane w Debug, więc nie sądziłem, że jest to powiązane. Zgodnie z tym, co mówisz, korzystałem z wersji Release CRT nawet z projektami debugowania. Dzięki jeszcze raz. –

+1

Tak, '/ MD' jest dynamicznym łączem do wydania CRT DLL; '/ MDd' jest dynamicznym łączem do debugowania CRT DLL. –

Powiązane problemy