Gostaria de saber se é possível detectar o delete
erro comentado abaixo em tempo de compilação? Especialmente, eu gostaria de ouvir sobre o compilador g ++.
ClassTypeA *abc_ptr = new ClassTypeA[100];
abc_ptr[10].data_ = 1;
delete abc_ptr; // error, should be delete []
c++
compiler
error-detection
SebGR
fonte
fonte
std::unique_ptr<ClassTypeA[]>
e então você não precisa.Respostas:
Em geral, o compilador não pode detectar esses erros. Exemplo: suponha que o construtor de alguma classe aloque algum membro de dados usando
new TypeName[]
, mas o destruidor usa erroneamente emdelete
vez dedelete[]
. Se o construtor e o destruidor são definidos em unidades de compilação separadas, como o compilador deve saber ao compilar o arquivo que define o destruidor que o uso é inconsistente com o do arquivo compilado separadamente que define o construtor?Com relação aos compiladores GNU, isso não acontece. Como observado acima, não pode ser feito no caso geral. Um compilador não precisa detectar erros de exclusão / exclusão diferentes porque esse é um comportamento indefinido. UB é o cartão "saia da cadeia" do fornecedor do compilador.
Ferramentas como o valgrind podem detectar esses tipos de incompatibilidades novas / excluídas, mas o fazem em tempo de execução. Pode haver uma ferramenta de análise estática que analisa todos os arquivos de origem que eventualmente serão compilados para formar um executável, mas eu não utilizo nenhuma ferramenta de análise estática que detecta esse tipo de erro.
fonte
Você pode usar as classes RAII apropriadas para
delete
. Esta é a única maneira segura de fazê-lo, e esse erro é apenas um dos muitos que você encontrará chamando adelete
si mesmo.Sempre use classes para gerenciar recursos dinâmicos da vida útil, e o sistema de tipos aplicará a destruição correta dos recursos.
Edit: "E se você estiver auditando o código e não puder alterá-lo?" Você está fodido.
fonte
Este erro em particular - sim. Esse tipo de erro geralmente: infelizmente não! Isso envolveria prever o fluxo de execução sem realmente executá-lo, e isso não é possível para programas arbitrários. (É por isso que a maioria dos compiladores nem tenta detectar casos simples como o seu exemplo.)
Portanto, a resposta do DeadMG é a apropriada: não tente acertar prestando atenção - a atenção humana é falível. Use os meios fornecidos pelo idioma e deixe o computador prestar atenção.
fonte
ClassTypeA*
para que você possa inserir uma linha entre o novo e o deleteif ( rand() % 2 == 1 ) abc_ptr = new ClassTypeA;
Nada no sistema de tipos estáticos está mostrando seabc_ptr
aponta para uma matriz ou objeto dinâmico ou parte de outro objeto ou matriz.abc_ptr
, caso contrário, como ele poderia desalocar a quantidade certa de memória? Portanto, o tempo de execução sabe quantos objetos devem ser desalocados.O caso trivial que você mostra pode ser detectado em tempo de compilação, porque a instanciação e a destruição do objeto estão no mesmo escopo. Em geral, a exclusão não está no mesmo escopo ou no mesmo arquivo de origem que a instanciação. E o tipo de um ponteiro C ++ não carrega informações sobre se ele faz referência a um único objeto de seu tipo ou matriz, sem falar no esquema de alocação. Portanto, não é possível diagnosticar isso em tempo de compilação em geral.
Por que não diagnosticar os casos especiais possíveis?
No C ++, já existem ferramentas para lidar com o vazamento de recursos dinâmicos vinculados a escopos, como ponteiros inteligentes e matrizes de nível superior (
std::vector
).Mesmo se você usar o
delete
sabor correto , seu código ainda não será seguro. Se o código entrenew[]
edelete[]
termina com uma saída dinâmica, a exclusão nunca é executada.No que diz respeito à detecção em tempo de execução, a
Valgrind
ferramenta faz um bom trabalho ao detectar isso em tempo de execução. Ver:Obviamente, o Valgrind não é executado em todas as plataformas, e nem sempre é prático ou possível reproduzir todas as situações de tempo de execução na ferramenta.
fonte
Alguns exemplos triviais de detecção em tempo de compilação / tempo de análise estática:
Em um host RHEL7 com
cppcheck 1.77 and 1.49
http://cppcheck.sourceforge.net/
Com
clang++ 3.7.1
no RHEL7O Clang Static Analyzer também pode detectar quando
std::unique_ptr
não é passado<char[]>
https://clang-analyzer.llvm.org/
Atualize abaixo com um link para o trabalho que adicionou isso ao clang, aos testes e a um bug que encontrei.
Isso foi adicionado ao clang com reviews.llvm.org/D4661 - "Detectar incompatibilidades 'novas' e 'excluir' usos" .
Os testes estão em test / Analysis / MismatchedDeallocator-checker-test.mm
Encontrei este bug aberto - bugs.llvm.org/show_bug.cgi?id=24819
fonte