Почему моя 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)

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

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

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

  • /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

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