Невозможно передать std::wstring через DLL
Я создал проект в Visual Studio 2010 для написания модульных тестов для существующей библиотеки MFC. Я использую фреймворк для модульного теста с одним заголовком и связан с библиотекой lib MFC DLL из проекта модульного теста. Я пытаюсь построить класс, который занимает std::wstring
в этом конструкторе. Вот как выглядит мой тест:
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);
}
куда Foobar
это класс, экспортируемый из тестируемой MFC DLL. Однако среда тестирования сообщает о неожиданном исключении. Я отследил это до std::wstring
конструктор копирования при копировании строки в Foobar
конструктор. Отладчик MSVC сообщает об исходной строке как <Bad Ptr>
,
Я создал фиктивный конструктор, Foobar::Foobar(long num, IDbService& db)
и все значения (включая IDbService&
) попадаются просто отлично.
И MFC DLL, и мой модульный тестовый EXE-файл совместно используют лист свойств, который должен поддерживать флаги компилятора эквивалентными. Я собираю и запускаю тест в режиме отладки. Любые идеи, почему std::wstring
не можете скопировать через DLL?
1 ответ
Вы должны проверить, что и EXE, и DLL динамически связаны с одной и той же CRT отладки (/MDd
опция компилятора). Убедитесь, что и другие настройки, такие как _HAS_ITERATOR_DEBUGGING
одинаковы для EXE и DLL.
(Ярлык может быть просто использовать const wchar_t*
вместо std::wstring
на интерфейсе класса, и просто построить std::wstring
из необработанного указателя внутри тела конструктора).
РЕДАКТИРОВАТЬ: Вы подтвердили, что CRT несоответствие (т.е. EXE, созданный с /MD
DLL против /MDd
) была проблема. Дело в том, что одно и то же имя класса std::wstring
означает два разных класса в отладочных сборках (/MDd
) и в сборках релиза (/MD
). Фактически, в отладочных сборках может быть дополнительная механика внутри реализации класса, чтобы помочь отладке; эта механика может привести к неэффективности, поэтому она удаляется в релизных сборках. Итак, внутренняя структура отладочной сборки std::wstring
отличается от релиза сборки std::wstring
(например, если вы пытаетесь распечатать сырой sizeof
из std::wstring
экземпляры, вы можете найти разные номера в сборках релизов и сборках отладки). Итак, EXE построен с /MD
ожидал релиз-билда std::wstring
; вместо этого DLL построена с /MDd
ожидал отладочной сборки std::wstring
: есть несоответствие между этими двумя ожиданиями (один модуль ожидает класс X
но другой модуль дает класс Y
) и поэтому у вас есть сбой.