Editar

Compartilhar via


Perguntas frequentes sobre DLL

Uma DLL do MFC pode criar vários threads?

Exceto durante a inicialização, uma DLL MFC pode criar vários threads com segurança, desde que use as funções de TLS (armazenamento local) do thread Win32, como TlsAlloc, para alocar o armazenamento local do thread. No entanto, se uma DLL MFC usar __declspec(thread) para alocar o armazenamento local do thread, o aplicativo cliente deverá estar implicitamente vinculado à DLL. Se o aplicativo cliente for explicitamente vinculado à DLL, a chamada para LoadLibrary não carregará a DLL com êxito. Para obter mais informações sobre variáveis locais de thread em DLLs, consulte thread.

Uma DLL MFC que cria um novo thread MFC durante a inicialização deixará de responder quando for carregada por um aplicativo. Isso inclui sempre que um thread é criado chamando AfxBeginThread ou CWinThread::CreateThread dentro:

  • O InitInstance de um objeto derivado de CWinApp em uma DLL MFC regular.

  • Uma função DllMain ou RawDllMain fornecida em uma DLL MFC regular.

  • Uma função DllMain ou RawDllMain fornecida em uma DLL de extensão MFC.

Um aplicativo multithread pode acessar uma DLL do MFC em threads diferentes?

Aplicativos de multithread podem acessar DLLs MFC regulares que vinculam dinamicamente as DLLs de extensão MFC e MFC de diferentes threads. Um aplicativo pode acessar DLLs MFC regulares que vinculam estaticamente ao MFC de vários threads criados no aplicativo.

Há alguma classe ou função do MFC que não pode ser usada em uma DLL do MFC?

As DLLs de extensão usam a classe derivada de CWinApp do aplicativo cliente. Eles não devem ter sua própria classe derivada de CWinApp.

DLLs do MFC regulares devem ter uma classe derivada de CWinApp e um único objeto dessa classe de aplicativo, assim como em um aplicativo do MFC. Diferente do objeto CWinApp de um aplicativo, o objeto CWinApp do DLL não tem uma bomba de mensagens principal.

Observe que o mecanismo CWinApp::Run não se aplica a uma DLL, pois o aplicativo é proprietário da bomba de mensagens principal. Se a DLL abrir caixas de diálogo sem modelo ou tiver uma janela própria de quadro principal, a bomba de mensagens principal do aplicativo deverá chamar uma rotina exportada pela DLL que, por sua vez, chamará a função membro CWinApp::PreTranslateMessage do objeto de aplicativo da DLL.

Quais técnicas de otimização devo usar para melhorar o desempenho do aplicativo cliente durante o carregamento?

Se a DLL for uma DLL MFC regular que esteja estaticamente vinculada ao MFC, alterá-la para uma DLL MFC regular vinculada dinamicamente ao MFC reduzirá o tamanho do arquivo.

Se a DLL tiver um grande número de funções exportadas, use um arquivo .def para exportar as funções (em vez de usar __declspec(dllexport)) e use o atributo NONAME do arquivo .def em cada função exportada. O atributo NONAME faz com que apenas o valor ordinal e não o nome da função sejam armazenados na tabela de exportação da DLL, o que reduz o tamanho do arquivo.

As DLLs que estão implicitamente vinculadas a um aplicativo são carregadas quando o aplicativo é carregado. Para melhorar o desempenho ao carregar, tente dividir a DLL em DLLs diferentes. Coloque todas as funções de que o aplicativo de chamada precisa imediatamente após o carregamento em uma DLL e faça com que o aplicativo de chamada vincule implicitamente a essa DLL. Coloque as outras funções de que o aplicativo de chamada não precisa imediatamente em outra DLL e tenha o aplicativo explicitamente vinculado a essa DLL. Para obter mais informações, consulte Vincular um executável a uma DLL.

Existe uma perda de memória na minha DLL MFC regular, mas meu código parece bom. Como posso encontrar a perda de memória?

Uma possível causa da perda de memória é que o MFC cria objetos temporários que são usados dentro de funções do manipulador de mensagens. Em aplicativos MFC, esses objetos temporários são limpos automaticamente na função CWinApp::OnIdle() que é chamada entre mensagens de processamento. No entanto, em DLLs (bibliotecas de vínculo dinâmico) do MFC, a função OnIdle() não é chamada automaticamente. Como resultado, os objetos temporários não são limpos automaticamente. Para limpar objetos temporários, a DLL deve chamar OnIdle(1) explicitamente periodicamente.