0

проект, на котором я работаю, загружает то же библиотеку дважды:Ссылка на одной и тот же DLL дважды - Явная и неявная одновременно

  1. с LoadLibrary
  2. статический загружает DLL с Lib файлом и "__declspec (dllimport/dllexport)".

Что происходит в этом случае? Эти две «нагрузки» используют ту же кучу или что-то другое. Например. это то же самое или аналогично вызову LoadLibrary дважды?

Моя общая проблема заключается в том, что у меня возникают проблемы с повреждением стека при вызове методов dll из exe через второй подход. И мне интересно, может ли проблема быть из-за первой загрузки? Все проекты используют один и тот же RT, выравнивание и т. Д.

+0

'LoadLibrary' не всегда загружает библиотеку. Вместо этого он может увеличить счетчик ссылок на уже загруженную DLL. –

+0

Кроме того, загрузка статических зависимостей ('dllimport') происходит до того, как вы сможете вызвать' LoadLibrary' (если вы не используете загрузку с задержкой), поэтому ваши номера противоположны действительности. –

+0

Вы нашли причину (скорее всего, в вашей динамической системе импорта dll/lib)? – CristiFati

ответ

3

По «статически загружает DLL с Lib файл и _declspec (DllImport/dllexport)» я предполагаю, вы имели в виду, что, что вы собрали свой исполняемый файл с .lib как зависимость, и в режиме исполнения .dll автоматически загружается exe (в начале). Вот фрагмент от FreeLibrary (surprisingly) MSDN page:

Система поддерживает подсчет ссылок на каждый процесс для каждого загруженного модуля. Модуль, который был загружен при инициализации процесса из-за динамической компоновки нагрузки, имеет счетчик ссылок. Счетчик ссылок для модуля увеличивается каждый раз, когда модуль загружается вызовом LoadLibrary. Счетчик ссылок также увеличивается при вызове LoadLibraryEx, если модуль не загружается в первый раз и загружается как файл данных или изображений.

Итак, другими словами, .dll загружается при запуске приложения (потому что вы связаны с ним) и LoadLibrary только увеличивает его порядковый счет(). Для получения дополнительной информации вы также можете проверить DllMain, или this dll guide.

Нет абсолютно никакой причины использовать оба подхода для одного и того же .dll в том же приложении.

2-й подход является предпочтительным, если .dll поставляется с .h файл (который содержит определения функций, экспортируемых библиотекой, необходимых во время компиляции) и .lib file (который инструктирует liker добавлять ссылки из файла .dll в исполняемый файл).

1-й подход, с другой стороны, является единственным способом, если у вас есть только файл .dll, и вы каким-то образом подписали функции, которые он экспортирует. В этом случае вы должны определить в своих указателях приложения эти функции и инициализировать их с помощью GetProcAddress. Бывают случаи, когда такой подход является предпочтительным, например, когда функциональность в .dll необходима только в угловом случае потока программы, в этом случае нет смысла связывать файл .lib и загружать .dll при запуске приложения, если, скажем, в 99% случаев он не понадобится. Кроме того, основное преимущество этого подхода: если .dll как-то удален, тогда только работающие с ним функции не будут работать (LoadLibrary не удастся), а при использовании другого подхода приложение не запустится.

Теперь, без деталей, я не могу добраться до нижней части этой конкретной проблемы, с которой вы столкнулись. Вы говорите, что вы вызываете функцию «обычно» (из ее определения в файле .h), она терпит неудачу, если вы ее вызываете (с теми же аргументами), используя указатель функции, это удается? Что такое сообщение об ошибке стека?

Примечание: Из моего опыта типичной причина стеки искаженных сценариев, как этот называет несоответствие конвенции между вызывающей и вызываемого (STDCALL против Cdecl или наоборот). Также смешение Отладка и Релиз может ввести проблемы.