11
votes

Pourquoi la suppression de vecteur est-elle appelée destructeurs à la suite d'une suppression scalaire?

J'ai du code qui se bloque dans un grand système. Cependant, le code revient essentiellement au pseudo-code suivant. J'ai enlevé une grande partie des détails, comme j'ai essayé de faire bouillir cela vers les os nus; Je ne pense pas que ce manque quoi que ce soit si important

                                ... FD FD FD FD
(address here)
VV VV VV VV MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
FD FD FD FD AB AB AB AB AB AB AB AB EE FE EE FE
...


6 commentaires

À Myclassimp, le CTor et DTor sont probablement appelés MyClassimp et non MyClass, n'est-ce pas?


Oh, et pouvez-vous f11 dans le nouveau ()? Laquelle est-ce ?


@ Calvin1602 [1] Merci, oui - j'ai corrigé cela maintenant. [2] Le C'TOR qui est appelé est celui de myClassimp après / pendant lequel celui de myClass est appelé.


Une fois que vous commencez à exporter des cours de DLL, la compilation avec / md devient très importante. On dirait / mt pour moi.


@Hans - c'est un indice aussi. Peut-être devriez-vous ajouter cela comme une réponse plutôt qu'un commentaire.


@Hanspassant pourquoi / md ou / mt fait une différence ici?


5 Réponses :


1
votes

Microsoft fournit la source de leur runtime C; Vous pouvez vérifier là pour voir ce que _crtisvalidheappointer fait. Sur mon installation, il est sous c: \ Program Files (x86) \ Microsoft Visual Studio 10.0 \ VC \ CRT \ SRC \ DBGHEAP.C .

Une autre suggestion est de vérifier le démontage de < / p> xxx

et le comparer au démontage généré pour xxx

et xxx

Pour tester votre théorie sur Suppr [] être appelé. De même, vous pouvez vérifier la pile d'appels pour xxx

pour tester votre théorie sur mydll_d.dll! Opérateur Suppr () Versus myexe_d. EXE! Opérateur Supprimer () .


0 commentaires

8
votes

On dirait que cela pourrait être un problème d'allouchement d'un tas et d'essayer de supprimer un autre. Cela peut être un problème lors de l'attribution d'objets d'une DLL car la DLL a son propre tas. Du code que vous montrez cela ne semble pas que ce soit le problème, mais peut-être dans la simplification que quelque chose a été perdu? Dans le passé, j'ai vu le code comme cette utilisation des fonctions d'usine et virtuel détruire sur les objets pour vous assurer que l'allocation et la suppression se produisent dans le code DLL.


1 commentaires

C'était certainement la clé de la réponse, de même que le commentaire de HANs sur la question (pour quoi, voir aussi ma propre «réponse»). Comme cela se produit, le code complet (plutôt que mon code de coupe) a effectivement des méthodes (), ainsi que des usines de création. Malgré cela, d'autres erreurs dans les paramètres de construction ont toujours conduit aux problèmes décrits.



1
votes

Merci pour toutes les réponses et commentaires. Tous ont été utiles et pertinents.

Toute information complémentaire est encore la bienvenue.


Ce qui suit était un commentaire sur ma question de Hans Passant:

Une fois que vous avez commencé à exporter des cours de DLL, La compilation avec / md devient très importante. On dirait que / mt à moi.

À la suite de cela, j'ai examiné de plus près le paramètre de liaison tout au long du projet. J'ai trouvé une instance "enterrée" de / mt et / mtd qui aurait dû être / MD et / MDD, plus certaines incohérences connexes dans d'autres contextes.

ayant corrigé ceux-ci, Aucun affirmation n'est maintenant lancé et le code semble se comporter correctement.


Voici quelques-unes des choses à vérifier lors de l'expérience des pannes ou des défaillances d'affirmation à l'exécution des leufs et des destructeurs sont appelés. Assurez-vous que dans tous les projets (y compris les dépendances) et dans toutes les configurations (surtout dans la problématique):

(ici les chemins * .vcproj sont par rapport à .)

  • le temps d'exécution correct est sélectionné dans C / C ++ | Génération de code | Bibliothèque d'exécution ;
  • Définitions appropriées (le cas échéant) sont fabriquées dans C / C ++ | Préprocesseur | Définitions de préprocesseur surtout à l'utilisation de bibliothèques dynamiques statiques contre (E. g. _stlp_use_static_lib versus _stlp_use_dynamic_lib for stlport);
  • Les versions appropriées des bibliothèques sont sélectionnées dans Linker | Entrée | Dépendances supplémentaires Particulièrement relative aux bibliothèques d'exécution statiques contre 'wrappers' pour les DLL (E.G. stlport_static.lib versus stlport. n.m .lib).

    Fait intéressant, le scalaire Scalar de Supprimer de la suppression que j'attends ne semble toujours pas être appelé (le point d'arrêt n'est jamais touché). C'est-à-dire que je ne vois toujours que le vecteur Supprimer le destructeur. Par conséquent, cela peut avoir été un "hareng rouge".

    Peut-être que c'est juste un problème de mise en œuvre de Microsoft, Ou peut-être qu'il y a encore une autre subtilité que j'ai manquée.


0 commentaires

1
votes

Ce comportement est spécial à MSVC 9, où l'opérateur de suppression d'une classe exportée, qui a un destructeur virtuel est généré implicitement et gisé à un dteur de vecteur avec un drapeau associé, où 1 moyen (scalaire) et 3 moyens (vecteur) .

Le vrai problème avec cette chose est que cela casse la forme canonique de nouvelle / supprimée, où le codeur client n'est pas en mesure de désactiver l'opérateur de suppression de vecteur dans son code, s'il pense que c'est une mauvaise idée de Utilisez-le.

De plus, le vecteur DTOR semble également être exécuté mal, si le nouveau est attribué dans un autre module que le module réside dans et se détient ensuite dans une variable statique via un compte de référence, ce qui l'exécute (ici Le vecteur DTTor entre en jeu) sur l'arrêt du processus.

Ceci correspond au problème du tas "Bshields" déjà mentionné précédemment, le DTOR est exécuté sur le mauvais tas et le code Crahses avec "Impossible de lire cet emplacement de mémoire" ou "Violation d'accès" à l'arrêt - ces problèmes semblent être très commun.

Le seul moyen de contourner ce bogue, c'est interdire l'utilisation d'un destructeur virtuel et l'exécuter le vôtre, en appliquant l'utilisation d'une fonction DELETE_Cette à partir de la classe de base - stupide, car c'est vous imiter la substance que le DTOR virtuel devrait faire pour vous. Ensuite aussi, le DTOR scalaire est exécuté et sur l'arrêt de tous les objets comptés de REF partagés entre les modules, peuvent être instanciés de manière sûre, car le tas est toujours traité correctement au module d'origine.

Pour vérifier, si vous avez de tels problèmes, interdisez simplement l'utilisation de l'opérateur de suppression de vecteur.


0 commentaires