Question

Dans ma demande, j'ai tout à fait un vide-pointeurs (ce qui est pour des raisons historiques, l'application a été écrit en pur C). Dans l'un de mes modules je sais que les points vides pointeurs vers des instances de classes qui pourraient hériter d'une classe de base connue, mais je ne peux pas être à 100% sûr. Par conséquent, faire un dynamic_cast sur le pointeur vide peut donner des problèmes. Peut-être, le pointeur vide même de points à une struct ordinaire (donc pas VPTR dans le struct).

Je voudrais enquêter sur les 4 premiers octets de la mémoire le pointeur vide pointe vers, pour voir si cela est l'adresse du vtable valide. Je sais que c'est la plate-forme, peut-être même compilateur spécifique à la version, mais il pourrait me aider à déplacer l'application vers l'avant, et se débarrasser de tous les vides-pointeurs sur une période limitée dans le temps (disons 3 ans).

Y at-il un moyen d'obtenir une liste de tous vtables dans l'application, ou un moyen de vérifier si un pointeur à un vtable valide, et si cette instance montrant les inherits vtable d'une classe de base connue?

Était-ce utile?

La solution

  

Je voudrais étudier la première   4 octets de la mémoire le pointeur vide   est en montrant, pour voir si tel est le   adresse du vtable valide.

Vous pouvez le faire, mais vous avez aucune garantie ne fonctionnera. Y ne sais même pas si le vide * pointera vers le vtable. La dernière fois que j'ai regardé dans cette (il y a 5 ans) Je crois que certains compilateur stocké le pointeur vtable avant l'adresse pointée par l'instance *.

  

Je sais que c'est la plate-forme, peut-être même   compilateur version spécifique,

Il peut également être compilateur-options speciffic, en fonction des optimisations que vous utilisez et ainsi de suite.

  

mais il pourrait me aider à déplacer le   Faire parvenir la demande, et de se débarrasser   de tous les vides-pointeurs sur une   période limitée dans le temps (disons 3   années).

Est-ce la seule option que vous pouvez voir pour déplacer l'application vers l'avant? Avez-vous envisagé d'autres?

  

Y at-il un moyen d'obtenir une liste de tous   vtables dans l'application,

Non: (

  

ou un moyen de vérifier si un pointeur   pointe vers un vtable valide,

pas de manière standard. Ce que vous pouvez faire est d'ouvrir des pointeurs de classe dans votre débogueur préféré (ou jeter la mémoire à octets et connectez-vous à un fichier) et de le comparer et voir si elle est logique. Même si, vous avez aucune garantie que l'un de vos données (ou d'autres pointeurs dans l'application) ne regarderons pas assez similaire (quand il est lancé en octets) Confondre quel que soit le code que vous aimez.

  

et si cette instance pointant   les vtable hérite d'une base connue   classe?

Non à nouveau.

Voici quelques questions (vous pouvez les avoir déjà considéré). Les réponses à ces questions peut vous donner plus d'options, ou peuvent nous donner d'autres idées à proposer:

  • Quelle est la taille base de code? Est-il possible d'introduire des changements globaux, ou la fonctionnalité de diffusion autour de cela?

  • traitez-vous tous les pointeurs de façon uniforme (qui est: y at-il des points communs dans votre code source où vous pouvez brancher et ajouter vos propres métadonnées)

  • Que pouvez-vous changer dans votre code source? (Si vous avez accès à votre allocation de mémoire ou des sous-routines pourrait brancher votre propre par exemple, vous pourrez peut-être brancher vos propres métadonnées).

  • Si différents types de données sont coulés à vide * dans différentes parties de votre code, comment décidez-vous plus tard ce qui est dans ces pointeurs? Pouvez-vous utiliser le code qui discrimine le vide * de décider si elles sont des classes ou non?

  • Est-ce que permettre à votre base de code pour les méthodes refactoring? (Refactoring en petites itérations, en branchant implémentations alternatives pour les parties de votre code, puis en enlevant la mise en œuvre et tout test initial)

Modifier (solution proposée):

Procédez comme suit:

  • définir une classe de métadonnées (base)

  • remplacer vos routines d'allocation de mémoire avec les personnalisés qui vient concernent les routines standard / vieux (et assurez-vous que votre code fonctionne toujours avec les routines personnalisées).

  • sur chaque allocation, allouer the requested size + sizeof(Metadata*) (et assurez-vous que votre code fonctionne toujours).

  • remplacer le premier sizeof(Metadata*) octets de votre allocation avec une séquence standard des octets que vous pouvez facilement test (je suis partielle 0xDEADBEEF: D). Ensuite, revenez [allocated address] + sizeof(Metadata*) à l'application. Sur désaffectation, prenez le pointeur recieved, par `décrémenter sizeof (métadonnées *), puis appelez le système / routine précédente pour effectuer la désaffectation. Maintenant, vous avez un tampon supplémentaire alloué dans votre code, en particulier pour les métadonnées de chaque allocation.

  • Dans les cas, vous êtes intéressé à avoir des métadonnées pour, créer / obtenir un pointeur de classe de métadonnées, puis définissez dans la zone 0xDEADBEEF. quand yous devez vérifier les métadonnées, reinterpret_cast<Metadata*>([your void* here]), décrémenter, puis vérifier si la valeur du pointeur est 0xDEADBEEF (pas métadonnées) ou autre chose.

Notez que ce code ne doit être là pour refactorisation - pour le code de production, il est lent, d'erreurs et généralement d'autres mauvaises choses que vous ne voulez pas que votre code de production soit. Je voudrais faire tout ce code dépendant de certains macro REFACTORING_SUPPORT_ENABLED qui ne permettra jamais que votre classe métadonnées pour voir la lumière d'une version de production (sauf pour les tests construit peut-être).

Autres conseils

Je dirais qu'il est impossible sans référence connexe (déclaration d'en-tête).

Si vous voulez remplacer les pointeurs vides type d'interface correcte, voici ce que je pense à automatiser:

  1. Allez dans votre base de code pour obtenir une liste de toutes les classes qui a des fonctions virtuelles, vous pouvez le faire rapidement par l'écriture de script, comme Perl

  2. Ecrire une fonction qui prend un pointeur void * comme entrée, et itérer sur ces classes essayer de dynamic_cast, et les informations du journal si réussi, comme le type d'interface, ligne de code

  3. Appelez cette fonction ne importe où vous avez utilisé le pointeur void *, vous pourriez peut-être l'envelopper avec une macro pour que vous puissiez obtenir le fichier, l'information en ligne facile

  4. Exécuter une automatisation complète (si vous avez) et analyser la sortie.

La façon plus facile serait de surcharge operator new pour votre classe de base particulière. De cette façon, si vous connaissez vos pointeurs vides * sont à des objets tas, alors vous pouvez également avec 100% de certitude de déterminer s'ils sont pointant vers votre objet.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top