Je voudrais savoir s'il est possible de détecter l' delete
erreur commentée ci-dessous au moment de la compilation? Surtout, j'aimerais entendre parler du compilateur g ++.
ClassTypeA *abc_ptr = new ClassTypeA[100];
abc_ptr[10].data_ = 1;
delete abc_ptr; // error, should be delete []
c++
compiler
error-detection
SebGR
la source
la source
std::unique_ptr<ClassTypeA[]>
et vous n'en avez pas besoin.Réponses:
En général, le compilateur ne peut pas détecter de telles erreurs. Exemple: supposons que le constructeur d'une classe alloue un membre de données à l'aide
new TypeName[]
, mais que le destructeur utilise par erreurdelete
au lieu dedelete[]
. Si le constructeur et le destructeur sont définis dans des unités de compilation distinctes, comment le compilateur doit-il savoir lors de la compilation du fichier qui définit le destructeur que l'utilisation est incompatible avec celle du fichier compilé séparément qui définit le constructeur?En ce qui concerne les compilateurs GNU, ce n'est pas le cas. Comme indiqué ci-dessus, il ne peut pas le faire dans le cas général. Un compilateur n'a pas à détecter de telles erreurs de nouvelle / suppression incompatibles car il s'agit d'un comportement non défini. UB est la carte «sortir de prison» du vendeur du compilateur.
Des outils tels que valgrind peuvent détecter et détectent ces types de disparités nouvelles / supprimées, mais le font au moment de l'exécution. Il pourrait y avoir un outil d'analyse statique qui examine tous les fichiers source qui seront éventuellement compilés pour former un exécutable, mais je ne connais aucun outil d'analyse statique qui détecte ce type d'erreur.
la source
Vous pouvez utiliser les classes RAII appropriées pour
delete
. C'est le seul moyen sûr de le faire, et cette erreur n'est que l'une des très, très nombreuses que vous rencontrerez endelete
vous appelant .Utilisez toujours des classes pour gérer les ressources dynamiques à vie, et le système de types appliquera la destruction des ressources correcte.
Edit: "Et si vous auditez le code et ne pouvez pas le changer?" Tu es foutu.
la source
Cette erreur particulière - oui. Ce genre d'erreur en général: malheureusement non! Cela impliquerait de prévoir le flux d'exécution sans l'exécuter réellement, et ce n'est pas possible pour les programmes arbitraires. (C'est pourquoi la plupart des compilateurs n'essaient même pas de détecter des cas simples comme votre exemple.)
Par conséquent, la réponse de DeadMG est la bonne: n'essayez pas de bien faire les choses en faisant attention - l'attention humaine est faillible. Utilisez les moyens fournis par la langue et laissez l'ordinateur faire attention.
la source
ClassTypeA*
donc vous pouvez insérer une ligne entre le nouveau et le supprimerif ( rand() % 2 == 1 ) abc_ptr = new ClassTypeA;
Rien dans le système de type statique ne montre si lesabc_ptr
points pointent vers un tableau ou un objet dynamique ou à mi-chemin dans un autre objet ou tableau.abc_ptr
, sinon comment pourrait-il être capable de désallouer la bonne quantité de mémoire? Le runtime sait donc combien d'objets doivent être désalloués.Le cas trivial que vous montrez peut être détecté au moment de la compilation, car l'instanciation et la destruction de l'objet ont la même portée. En général, la suppression n'a pas la même portée, ni même le même fichier source, que l'instanciation. Et le type d'un pointeur C ++ ne contient pas d'informations sur s'il fait référence à un seul objet de son type ou à un tableau, sans parler du schéma d'allocation. Il n'est donc pas possible de diagnostiquer cela au moment de la compilation en général.
Pourquoi ne pas diagnostiquer les cas particuliers qui sont possibles?
En C ++, il existe déjà des outils pour gérer les fuites de ressources dynamiques liées aux étendues, à savoir les pointeurs intelligents et les tableaux de niveau supérieur (
std::vector
).Même si vous utilisez la bonne
delete
saveur, votre code n'est toujours pas sûr d'exception. Si le code entre lenew[]
et sedelete[]
termine par une sortie dynamique, la suppression ne s'exécute jamais.En ce qui concerne la détection au moment de l'exécution, l'
Valgrind
outil fait un bon travail de détection lors de l'exécution. Regarder:Bien sûr, Valgrind ne fonctionne pas sur toutes les plates-formes, et il n'est pas toujours pratique ou possible de reproduire toutes les situations d'exécution sous l'outil.
la source
Quelques exemples triviaux de détection au moment de la compilation / de l'analyse statique:
Sur un hôte RHEL7 avec
cppcheck 1.77 and 1.49
http://cppcheck.sourceforge.net/
Avec
clang++ 3.7.1
sur RHEL7L'analyseur statique Clang peut également détecter quand il
std::unique_ptr
n'est pas passé<char[]>
https://clang-analyzer.llvm.org/
Mettez à jour ci-dessous avec un lien vers le travail qui l'a ajouté à clang, les tests et un bug que j'ai trouvé.
Cela a été ajouté à clang avec reviews.llvm.org/D4661 - «Détecter les utilisations« nouvelles »et« supprimer »incompatibles» .
Les tests sont dans test / Analysis / MismatchedDeallocator-checker-test.mm
J'ai trouvé ce bogue ouvert - bugs.llvm.org/show_bug.cgi?id=24819
la source