Será que uma fuga de memória no descarregamento de uma DLL causa um vazamento no processo de acolhimento?
-
02-07-2019 - |
Pergunta
Considere este caso:
dll = LoadDLL()
dll->do()
...
void do() {
char *a = malloc(1024);
}
...
UnloadDLL(dll);
Neste ponto, será o 1k alocados na chamada para malloc () estar disponível para o processo de host de novo? A DLL está vinculado estaticamente a CRT.
Solução
Não, você não escapam.
Se você misturar dll modelos (estático e dinâmico), então você pode acabar com um erro de memória se você alocar memória em uma dll, que você libertar em um diferente (ou libertado no exe)
Isto significa que a pilha criado pela CRT estaticamente ligado não é a mesma pilha como CRT de uma dll diferente.
Se você tivesse ligado com a versão dinâmica do CRT, então você tem um vazamento como a pilha é compartilhado entre todos os CRTs dinamicamente ligadas. Isso significa que você deve sempre projetar seus aplicativos para usar os CRTs dinâmicas, ou garantir que você nunca gerenciar a memória em um limite de dll (ou seja, se você alocar memória em uma dll, sempre fornecem uma rotina para libertá-lo da mesma dll)
Outras dicas
-
Memória usada por um processo como monitorado pelo sistema operacional é aplicável a todo o processo e não é específico para um DLL.
-
A memória é dado ao programa em pedaços pela OS, chamados montes
-
Os gerentes heap (malloc / new etc) ainda dividir os pedaços e as mãos para fora para solicitar o código.
-
Somente quando uma nova pilha é alocado é o sistema operacional detectar um aumento na memória.
-
Quando uma DLL é ligado estaticamente para a biblioteca tempo de execução C (CRT), uma cópia privada do CRT com as funções CRT que chama de código da DLL é compilado e colocado em binário do DLL. Malloc também é inclued neste.
-
Esta cópia privada de malloc será invocado sempre que o código presente dentro da DLL estaticamente ligado tenta alocar memória.
-
Por isso, um montão privado visível apenas para esta cópia do malloc, é adquirida a partir do OS por este malloc e aloca a memória solicitada pelo código dentro deste montão privado.
-
Quando os descarrega DLL, ele descarrega seu acervo particular e esse vazamento passa despercebida como toda a pilha é devolvido de volta para o OS .
-
No entanto, se a DLL é dinamicamente ligado, a memória é alocada por uma versão compartilhada do malloc, global a todo o código que está ligada no modo compartilhado.
-
A memória alocada por este malloc global, sai de uma pilha que é também a pilha usada para todos os outros códigos que está ligada no modo aka compartilhada dinâmica e, portanto, é comum. Todas as fugas provenientes este montão, portanto, torna-se um vazamento que afeta todo o processo.
Edit -. Descrições do cenário ligando Adicionado
Você não pode dizer. Isso depende da implementação de sua estática e CRT dinâmica. Pode até depender do tamanho da atribuição, pois há CRTs que a frente grandes alocações para o sistema operacional, mas implementar sua própria pilha para pequenas alocações.
O problema com a CRT que vazamentos é claro que ele vazamentos. O problema com a CRT, que não vazamento faz é que o poder executável razoável esperar para usar a memória, como memória malloc'ed deve permanecer utilizável até livre é chamado.
De MSDN potenciais erros Passando CRT objetos através limites DLL
Cada cópia da biblioteca CRT tem um estado separado e distinto. Assim sendo, CRT objetos como identificadores de arquivo, variáveis ??de ambiente e locais são válido apenas para a cópia da CRT onde esses objetos são alocados ou conjunto. Quando uma DLL e seu uso usuários diferentes cópias da biblioteca CRT, você não pode passar essas CRT objetos através do limite DLL e esperam -los para ser apanhada corretamente no outro lado.
Além disso, porque cada cópia do CRT biblioteca tem seu próprio gerenciador de heap, alocação de memória em um biblioteca CRT e passando o ponteiro através de uma DLL limite a ser libertado por um diferente cópia da biblioteca CRT é um potencial causa para a corrupção de pilha.
Espero que isso ajude.
Na verdade, a resposta marcada está incorreto. Esse direito existe uma fuga. Embora seja tecnicamente viável para cada DLL para implementar o seu próprio montão, e libertá-lo no desligamento, a maioria dos montes "tempo de execução" - estático ou dinâmico - são wrappers para o Win32 pilha do processo API
.A menos que se tenha tomado cuidados específicos para garantir que este não é o caso, a dll vai vazar a alocação por carga, fazer, ciclo de descarga.
Pode-se fazer um teste e ver se há vazamentos de memória. Você executar um teste simples de 30 vezes alocar 1 MB de cada vez. Você deve descobrir isso muito rapidamente.
Uma coisa é certa. Se você memória alocada na DLL você também deve liberar essa memória lá (na DLL).
Por exemplo, você deve ter algo como isto (simples, mas pseudocódigo intuitivo):
dll = DllLoad();
ptr = dll->alloc();
dll->free(ptr);
DllUnload(dll);
Isto deve ser feito porque a DLL tem uma pilha diferente do que o processo original (que carrega a DLL).