Вопросы и ответы по библиотекам DLL

Допускается ли создание в библиотеке DLL MFC нескольких потоков?

За исключением инициализации, библиотека DLL MFC может безопасно создавать несколько потоков, если в ней используются функции локального хранилища (TLS) потока Win32, такие как TlsAlloc, для выделения локального хранилища потоков. Однако если библиотека DLL MFC использует __declspec(thread) для выделения локального хранилища потоков, клиентское приложение должно быть неявно связано с библиотекой DLL. Если клиентское приложение явно ссылается на библиотеку DLL, вызов LoadLibrary не загрузит библиотеку DLL. Дополнительные сведения о локальных переменных потока в библиотеках DLL см. в разделе о потоке.

Библиотека DLL MFC, которая создает новый поток MFC во время запуска, перестает отвечать на запросы при загрузке приложением. Это происходит каждый раз при создании потока путем вызова AfxBeginThread или CWinThread::CreateThread внутри следующих элементов:

  • InitInstance объекта, производного от CWinApp, в обычной библиотеке DLL MFC.

  • Переданная функция DllMain или RawDllMain в обычной библиотеке DLL MFC.

  • Переданная функция DllMain или RawDllMain в библиотеке DLL расширения MFC.

Допускается ли обращение к библиотеке DLL MFC из многопоточного приложения в различных потоках?

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

Какие классы и функции MFC не могут использоваться в библиотеке DLL MFC?

Библиотеки DLL расширения используют класс, производный от CWinApp, клиентского приложения. Они не должны иметь собственный класс, производный от CWinApp.

Обычные библиотеки DLL MFC должны иметь класс, производный от CWinApp, и один объект этого класса приложения так же, как и приложение MFC. В отличие от объекта CWinApp приложения, у объекта CWinApp библиотеки DLL нет основного генератора сообщений.

Обратите внимание, что механизм CWinApp::Run не применяется к библиотеке DLL, так как в приложении есть основной генератор сообщений. Если библиотека DLL открывает немодальные диалоговые окна или имеет собственное основное окно кадра, основной генератор сообщений приложения должен вызвать подпрограмму, экспортированную библиотекой DLL, которая, в свою очередь, вызывает функцию-член CWinApp::PreTranslateMessage объекта приложения библиотеки DLL.

Методы увеличения скорости загрузки клиентского приложения

Если библиотека DLL является обычной библиотекой DLL MFC, которая статически связана с MFC, то изменение ее на обычную библиотеку DLL MFC, которая динамически связана с MFC, сокращает размер файла.

Если в библиотеке DLL содержится большое количество экспортированных функций, используйте DEF-файл для экспорта функций (вместо использования __declspec(dllexport)), а также атрибут NONAME DEF-файла для каждой экспортированной функции. Атрибут NONAME приводит к сохранению только порядкового значения, а не имени функции в таблице экспорта библиотеки DLL, что сокращает размер файла.

Библиотеки DLL, которые неявно связаны с приложением, загружаются при загрузке приложения. Чтобы повысить производительность при загрузке, попробуйте разделить библиотеку DLL на разные библиотеки DLL. Помещайте все функции, необходимые вызывающему приложению сразу после загрузки, в одну библиотеку DLL, и настройте вызывающее приложение для неявной связи с этой библиотекой DLL. Помещайте остальные функции, которые не нужны вызывающему приложению сразу, в другую библиотеку DLL, и настройте вызывающее приложение для явной связи с этой библиотекой DLL. Дополнительные сведения см. в разделе Связывание исполняемого файла с библиотекой DLL.

В обычной библиотеке DLL MFC обнаружена утечка памяти, однако видимые ошибки в коде отсутствуют. Как найти утечку памяти?

Одной из возможных причин утечки памяти является тот факт, что MFC создает временные объекты, используемые внутри функций обработчика сообщений. В приложениях MFC эти временные объекты автоматически очищаются в функции CWinApp::OnIdle(), которая вызывается между сообщениями обработки. Однако в библиотеках динамической компоновки (DLL) MFC функция OnIdle() не вызывается автоматически. В результате временные объекты не очищаются автоматически. Чтобы очистить временные объекты, библиотека DLL должна периодически явно вызывать OnIdle(1).