Pergunta

Se eu usar a palavra-chave new em minha biblioteca (que é construído de forma diferente do meu aplicativo principal), quando eu excluí-lo em meu aplicativo principal com delete, há uma chance de que eu possa ter uma colisão / erro?

Foi útil?

Solução

Sim indeedy. Em particular, você vê problemas com montes debug / release ser diferente, também se colocação seus usos biblioteca nova, ou qualquer personalizado pilha você terá um problema. A questão debug / release é de longe o mais comum embora.

Outras dicas

Depende. Se você está falando de uma biblioteca estática, então você provavelmente vai ser OK - o código será executado no mesmo contexto como o programa principal, usando a mesma biblioteca C ++ runtime. Isto significa que new e delete vai usar a mesma pilha.

Se você está falando de uma biblioteca compartilhada (a DLL), então você provavelmente não vai ser OK. O código em execução na DLL pode estar usando uma biblioteca de tempo de execução diferente C ++, o que significa que o layout da pilha será diferente. O DLL pode estar usando uma pilha totalmente diferente.

Chamando delete (no programa principal) em um ponteiro alocado pelo DLL (ou vice-versa) vai levar a (na melhor das hipóteses) um acidente de imediato ou (na pior das hipóteses) de corrupção de memória que vai demorar um pouco para rastrear.

Você tem um par de opções. A primeira é usar o padrão "método de fábrica" ??para criar e excluir esses objetos:

Foo *CreateFoo();
void DeleteFoo(Foo *p);

Estes devem não ser implementado no cabeçalho do arquivo.

Como alternativa, você pode definir um método Destroy sobre o objeto:

class Foo
{
    ~Foo();

public:
    virtual void Destroy();
};

... novamente, não implementar isso no arquivo de cabeçalho. Você iria implementá-lo assim:

void Foo::Destroy()
{
    delete this;
    // don't do anything that accesses this object past this point.
}

Note que o destruidor para Foo é privado, de modo que você tem que Foo::Destroy chamada.

Microsoft COM faz algo semelhante, onde se define um método Release que exclui o objeto quando a sua contagem de referência cai para zero.

Sim, você vai. Uma solução simples é fornecer Criar e funções excluir na sua biblioteca que pode ser chamado a partir da aplicação principal. A função Criar irá executar o novo e retornar um ponteiro, que é mais tarde passou para a função Apagar para exclusão.

É um problema que eu só vi no Windows.

Os sistemas Unixish não fazer um hábito de forçar bibliotecas compartilhadas para ligação a diferentes versões da mesma biblioteca dentro do mesmo programa e todos os símbolos carregados são globalmente visível. Isso significa que se um objeto é alocado em uma parte do código e eliminada em outra, ambos estão usando a mesma biblioteca de sistema para fazê-lo.

Eu tenho que dizer, este problema Windows cria com as suas diversas DLLs C tempo de execução é realmente irritante e pouco natural para um programador C. Olhe para a biblioteca C; tem funções como strdup que malloc a corda e esperar que o programador para chamar free () sobre ele. Mas fazer a mesma coisa em sua própria biblioteca no Windows e apenas esperar pela explosão. Você vai ter que esperar, também, porque isso não vai acontecer durante o desenvolvimento, mas só depois que você deu a DLL compilado para algum outro pobre coitado.

Old New Thing cobriu isso antes . Ele também dá uma lista das principais soluções da Microsoft.

Você está certo de que há um problema lá, mas para a maioria dos casos não há uma solução ainda mais simples do que as outras respostas (até agora) têm propostas. Você pode continuar a usar nova e excluir livremente -. Tudo o que você precisa fazer é a sobrecarga de novo e excluir para cada classe em sua biblioteca que pode ser usado através de fronteiras DLL

Pessoalmente, eu só definida uma classe simples para fornecer a funcionalidade necessária:

class NewDelete
{
    public:
        void *operator new (size_t size);
        void operator delete (void *memory);
        void *operator new (size_t size, void *ptr);
        void operator delete (void *memory, void *ptr);
};

Enquanto essas quatro funções membro são todos definidos na mesma DLL, então qualquer classe que deriva desta classe é automaticamente "DLL-safe" - novo e excluir pode ser usado normalmente sobre eles sem se preocupar com limites de DLL.

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