Como forçar o fim destruição de objetos estáticos em diferentes dlls?
-
22-08-2019 - |
Pergunta
Eu tenho 2 estática objetos em 2 DLLs diferentes :
Um objeto Resources (que é um singleton), e um objeto Usuário . Objeto de usuário no seu destrutor tem de Recursos de acesso a objetos.
Como posso forçar Recursos objeto não deve ser destruído antes objeto de usuário?
Solução
Objetos globais são destruídos quando sua DLL correspondente é descarregada. Assim como seu dll 'User' é provavelmente dependente de sua dll 'Recursos', você está em apuros:. 'Recurso' sempre será destruído antes 'usuário'
Eu também estou interessado por uma boa resposta a esta pergunta, se existir. Até agora, eu estou usando uma função de limpeza que deve ser chamado pelo aplicativo antes de ele sai, e eu só manter o código inofensivo em destruidores.
Outras dicas
Se você é capaz de colocar que 2 variáveis ??globais na mesma DLL não é a mesma história. Como dito por Jem em sua própria resposta, a fim Destacamento DLL não é garantida pelo sistema. Portanto, você pode ter um grande problema quando se tem 2 DLLs separadas. Eu não sou um guru do sistema Windows, mas ter um olhar com o Google, eu encontrei bloggers do MSDN que diz que eles tinham o mesmo problema com nenhuma boa solução para enfrentá-lo.
Eu você é capaz de colocá-los em uma mesma DLL, de acordo com mim a solução é mais fácil, nesse caso, você não precisa lidar com o "não GARANTIDO DLL Destacamento fim" questão (insolúvel, tanto quanto eu entendo) .
Mas, então, você ainda precisa enfrentar um novo problema: ordem global destruição variável não é garanteed pela linguagem C ++. Mas este pode ser abordada:
você precisa usar algum tipo de couting referência. um boost :: shared_ptr pode fazer o truque.
Declare-global e defini-lo dessa forma:
boost::shared_ptr my_resource_ptr ( new Resource() ); // new operator is important here!
Em seguida, você precisa modificar sua implementação de Usuário para Fechar o seu próprio shared_ptr:
class User
{
...
boost::share_ptr a_resource_ptr;
...
};
Enquanto todos um da sua instância do usuário não é destruída, os vai 'reter' a instância de recurso, e assim impedir que ele seja prematuraly excluído, mesmo que o shared_ptr global poderia ter sido destruído.
A última instância do usuário sendo destruído vai (undirectly) excluir a instância de recurso.
Seja qual for a contagem de referência que você usa, ComPtr, seu próprio, ele deve fazer o truque.
Eu não acho que você pode alterar a ordem de destruição de globals que estão em módulos diferentes. Qualquer chance de adicionar algum contagem de referência?
No caso de você realmente deseja obter 2 separados PostRunOnce I pode ter algumas dicas para você: você pode considerar o uso de FreeLibrary()
do Windows API. Tal como indicado por msdn FreeLibrary()
decrementos um contador de referência para a DLL que é descarregado quando o contador chegar a 0.
Drawback: usando FreeLibrary()
implica que você está carregando-lo com LoadLibrary()
( ligação MSDN) e chamando a função desta biblioteca implica que você está usando a função GetProcAddress()
, o que pode levar a um código muito feio. E isso pode implicar alguma mudança no seu código também - como a obtenção de poiting variável global para as funções da DLL no fim de armazenar o endereço uns dos funções ...
Se você quiser implementá-lo:
- você deve carregar e libertar a biblioteca de sua função
main()
do seu processo, - e também carregar e libertar a biblioteca da DLL implenting a classe de usuário. Implementá-lo na função
DllMain()
para este DLL, quando a razão éDLL_PROCESS_DETACH
(veja o MDSN DllMain ligação .
Assim, ele irá descarregar a biblioteca "Resource" apenas uma vez a biblioteca "Usuário" tem acabamento com ele.
Tenha uma tentativa se você quiser e deixe-me dizer se ele funciona como eu nunca implementou ..
Ps: Eu tenho segunda resposta posta à sua pergunta para obter uma separação significativa entre as duas respostas como eu (tente) Detalhe ambos. Eu não quero que você misturá-las e ficar confuso ...