Pergunta

Eu sei que nova-ing algo em um módulo e excluir-ing-lo em outro muitas vezes pode causar problemas no VC ++. Problemas com diferentes tempos de execução. Misturando módulos com tempos de execução staticly ligados e / ou ligadas dinamicamente versões descasamentos ambos podem estragar o material acima, se bem me lembro.

No entanto, é seguro usar VC ++ 2008 é std :: tr1 :: shared_ptr através dos módulos?

Uma vez que existe apenas uma versão do tempo de execução que mesmo sabe o que é um shared_ptr é, vinculação estática é o meu único perigo (por agora ...). Eu pensei que eu li que a versão de impulso de um shared_ptr era seguro usar como este, mas eu estou usando a versão de Redmond ...

Eu estou tentando evitar ter uma chamada especial para objectos livres no módulo de alocação. (Ou algo como um "deletar essa" na própria classe). Se tudo isso parece um pouco hacky, estou usando isso para o teste de unidade. Se você já tentou teste de unidade de código C ++ existente que você possa compreender como criativo você precisa ser às vezes. Minha memória é alocada por um EXE, mas no final será liberado em uma DLL (se a contagem de referência funciona da maneira que eu acho que ele faz).

Foi útil?

Solução

liberar a memória é seguro, desde que tudo veio do mesmo gerenciamento de memória contexto. Você identificou o problema mais comum (tempos de execução diferente C ++); tendo montões separados é outro problema menos comum você pode executar em.

Outra questão que você não mencionou, mas que pode ser exascerbated por ponteiros compartilhados, é quando existe o código de um objeto no DLL e é criado pela DLL, mas outro objeto fora do DLL termina com uma referência a ele (através de ponteiro partilhada). Se esse objeto é destruído após a DLL é descarregada (por exemplo, se é uma estática do nível de módulo, ou se a DLL é explicitamente descarregada por FreeLibrary(), destruidor do objeto compartilhado irá falhar.

Isto pode mordê-lo se você tentar escrever baseados em DLL, plugins fracamente acoplados. É também a razão que COM permite DLLs decidir quando eles pode ser descarregados, em vez de deixar servidores COM exigir-descarregá-los.

Outras dicas

Você está começando a ver quão incrivelmente surpreendente shared_ptr é:)

Ser seguro através de fronteiras DLL é exatamente o que shared_ptr foi projetado para ser (entre outras coisas, é claro).

Ao contrário do que já foi dito, você não precisa mesmo de passar por um deleter personalizado ao construir o shared_ptr, como o padrão já é algo como

template <typename T>
struct default_deleter {
    void operator()( T * t ) { delete t; }
};

e

shared_ptr<Foo> foo( new Bar );

é equivalente a

shared_ptr<Foo> foo( new Bar, default_deleter<Bar>() );

(ie., Não há tal coisa como um shared_ptr sem deleter).

Por causa da eliminação de tipo realizado no deleter, o delete que é chamado de vão sempre ser o único do DLL que instanciado o shared_ptr, não a do DLL onde o último shared_ptr sai do escopo (ie. a shared_ptr invocando o deleter vai chamá-lo através de um ponteiro para uma função colocado lá pelo shared_ptr original).

Compare isso com auto_ptr, que incorpora o operador delete diretamente em sua (in-line) destructor, o que significa que o delete da DLL que destrói o auto_ptr é usado, criando os mesmos problemas que a exclusão de um ponteiro nu.

Pela mesma técnica, as classes polimórficas que são sempre realizadas em shared_ptrs nem sequer precisa de um destrutor virtual, porque o deleter sempre chamar o destruidor certo, mesmo quando o último shared_ptr para ir fora do escopo é um instanciado para o classe base.

Se você está interessado, use o formulário de construtor shared_ptr que leva um argumento deleter. O deleter pode chamar de volta para o módulo que alocou o objeto para que a exclusão ocorre no contexto adequado.

documentação reivindicações de impulso que é 100% compatível com TR1, por isso espero que não há nada enganoso sobre isso:

http://www.boost.org /doc/libs/1_37_0/libs/smart_ptr/shared_ptr.htm#constructors

Eu acho que é tão seguro quanto usar qualquer uma das classes em std através dos módulos.

Isto é:. Deve ser seguro se os módulos usam exatamente a mesma biblioteca de tempo de execução, e exatamente o mesmo compilador muda e as opções

Nunca usar a biblioteca de tempo de execução estática, como cada módulo terá a sua própria instância de todos os globals dentro dela.

O melhor conselho que eu vi sobre o tema geral é que a memória deve ser desalocada no mesmo contexto que está alocado. Isso não impede que uma biblioteca de passagem de volta um ponteiro que o código do aplicativo é suposto libertar no entanto, então eu diria que você é provavelmente seguro passar o shared_ptr desta maneira, porque é a mesma situação geral.

Se a semântica do seu sistema significa que o ponteiro é realmente transferido (no sentido de propriedade) de seu exe para sua DLL, em seguida, um auto_ptr pode ser uma solução melhor. Se, no entanto, o ponteiro é verdadeiramente compartilhada, então o shared_ptr é provavelmente a melhor solução.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top