Почему моя DLL не требует функции DllMain?

Я только что добавил проект C++ Windows DLL в решение Visual Studio (2022). Волшебник поставил DllMain там. Это бросилось мне в глаза; Я не помню, чтобы в других моих DLL были функции DllMain;

При поиске в моем коде оказалось, что ни одна из моих 9 DLL не имеет функций DllMain. Тем не менее, все они строятся и работают нормально. Я проверил настройки проекта для всех этих проектов:

  • Ни у одного из них не установлен параметр компоновщика /NOENTRY.
  • Все они имеют /SUBSYSTEM:WINDOWS набор.
  • Ни у одного из них не установлен параметр компоновщика /NODEFAULTLIB.
  • Они, безусловно, все DLLS.

Поэтому я закомментировал этот DllMain в новом проекте, который я только что добавил. До сих пор нормально строится.

Мои знания явно устарели. Я думал, что DllMain раньше требовалось. Я помню, как много лет назад у меня возникали ошибки компоновщика в моих библиотеках DLL, когда я не мог добавить DllMain.

Итак, мои вопросы:

  1. Почему для моих библиотек DLL не требуется DllMain? Есть ли какие-то настройки сборки, которые я не проверил?
  2. Есть ли минус в том, что его нет?

(Обратите внимание, что все эти библиотеки DLL экспортируют классы C++. Ни одна из них не является ресурсной библиотекой DLL. Все работают нормально в течение 6 лет. Некоторые из них используют локальное хранилище потока. Некоторые из них имеют статические переменные внутри функций. Я всегда думал, что использование такие вещи требовали DllMain)

Получение данных из формы с помощью JavaScript - краткое руководство
Получение данных из формы с помощью JavaScript - краткое руководство
Получить данные из формы с помощью JS очень просто: вы запрашиваете элемент формы, передаете его конструктору new FormData() и, наконец, получаете...
Пользовательские правила валидации в Laravel
Пользовательские правила валидации в Laravel
Если вы хотите создать свое собственное правило валидации, Laravel предоставляет возможность сделать это. Создайте правило с помощью следующей...
3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
1
0
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Библиотека времени выполнения («CRT» = библиотека времени выполнения C/C++) предоставляет точку входа настоящий DLL _DllMainCRTStartup, которая делает такие вещи, как инициализация глобальных переменных перед вызовом вашего DllMain. В MSDN есть документация, которая описывает это:

Также актуальна документация опции компоновщика /ENTRY:

Существует также предоставляемый библиотекой слабый символ для вашего DllMain, поэтому вызов из реальной точки входа в DllMain не завершается ошибкой во время компоновки с неразрешенным внешним. Из первого документа выше:

By default, if you do not provide a DllMain function, Visual Studio provides one for you and links it in so that _DllMainCRTStartup always has something to call.

Упомянутые вами вещи, такие как локальное хранилище потока, требуют использования точки входа, предоставляемой библиотекой; они сломаются, если вы используете опцию /ENTRY для link.exe, чтобы заменить точку входа в библиотеку своей собственной, или /NOENTRY, чтобы отключить ее. Ни один из них не требует каких-либо действий со стороны DllMain, которую вызывает точка входа в библиотеку.

Итак, если я помню, что мне нужно определить DllMain, чтобы заставить DLL работать, это просто плохая память с моей стороны? Я мог бы поклясться, что так оно и было. Но я не возился с DllMain почти 20 лет.

Joe 06.04.2022 19:33

@Joe: Написание собственного DllMain никогда не было необходимо, если поведение, предоставляемое библиотекой, было достаточно хорошим.

Ben Voigt 06.04.2022 19:34

Хорошо, тогда весь этот вопрос был важным моментом. Спасибо, что нашли время ответить

Joe 06.04.2022 19:34

@Joe: Я думаю, вы, возможно, помните поведение, связанное с файлом .DEF, который мастера использовали для создания (до того, как существовала система __declspec(dllexport), там должен был быть указан экспорт). Если вы удалите какие-либо функции, созданные мастером (например, DllCanUnloadNow или DllRegisterServer) из исходного кода C/C++, но не удалите их из файла .DEF, вы получите ошибки ссылок.

Ben Voigt 06.04.2022 19:37

Другие вопросы по теме