C'est incroyable la quantité d'informations trompeuses que vous pouvez lire dans les articles ci-dessus ...
Et même dans la documentation Microsoft MSDN, IsBadPtr est censé être interdit. Eh bien, je préfère une application qui fonctionne plutôt que de planter. Même si le travail à terme peut ne pas fonctionner correctement (tant que l'utilisateur final peut continuer avec l'application).
En googlant, je n'ai trouvé aucun exemple utile pour Windows - j'ai trouvé une solution pour les applications 32 bits,
http://www.codeproject.com/script/Content/ViewAssociatedFile.aspx?rzp=%2FKB%2Fsystem%2Fdetect-driver%2F%2FDetectDriverSrc.zip&zep=DetectDriverSrc%2FDetectDriver%2FsrcF%2Fdrobid.c. = 2
mais je dois également prendre en charge les applications 64 bits, donc cette solution n'a pas fonctionné pour moi.
Mais j'ai récolté les codes sources de wine et j'ai réussi à cuisiner un type de code similaire qui fonctionnerait également pour les applications 64 bits - en attachant le code ici:
#include <typeinfo.h>
typedef void (*v_table_ptr)();
typedef struct _cpp_object
{
v_table_ptr* vtable;
} cpp_object;
#ifndef _WIN64
typedef struct _rtti_object_locator
{
unsigned int signature;
int base_class_offset;
unsigned int flags;
const type_info *type_descriptor;
//const rtti_object_hierarchy *type_hierarchy;
} rtti_object_locator;
#else
typedef struct
{
unsigned int signature;
int base_class_offset;
unsigned int flags;
unsigned int type_descriptor;
unsigned int type_hierarchy;
unsigned int object_locator;
} rtti_object_locator;
#endif
/* Get type info from an object (internal) */
static const rtti_object_locator* RTTI_GetObjectLocator(void* inptr)
{
cpp_object* cppobj = (cpp_object*) inptr;
const rtti_object_locator* obj_locator = 0;
if (!IsBadReadPtr(cppobj, sizeof(void*)) &&
!IsBadReadPtr(cppobj->vtable - 1, sizeof(void*)) &&
!IsBadReadPtr((void*)cppobj->vtable[-1], sizeof(rtti_object_locator)))
{
obj_locator = (rtti_object_locator*) cppobj->vtable[-1];
}
return obj_locator;
}
Et le code suivant peut détecter si le pointeur est valide ou non, vous devez probablement ajouter une vérification NULL:
CTest* t = new CTest();
//t = (CTest*) 0;
//t = (CTest*) 0x12345678;
const rtti_object_locator* ptr = RTTI_GetObjectLocator(t);
#ifdef _WIN64
char *base = ptr->signature == 0 ? (char*)RtlPcToFileHeader((void*)ptr, (void**)&base) : (char*)ptr - ptr->object_locator;
const type_info *td = (const type_info*)(base + ptr->type_descriptor);
#else
const type_info *td = ptr->type_descriptor;
#endif
const char* n =td->name();
Cela obtient le nom de la classe du pointeur - je pense que cela devrait suffire à vos besoins.
Une chose qui, je le crains encore, est la performance de la vérification des pointeurs - dans l'extrait de code ci-dessus, il y a déjà 3-4 appels d'API en cours - pourrait être excessive pour les applications critiques en temps.
Ce serait bien si quelqu'un pouvait mesurer la surcharge de la vérification du pointeur par rapport, par exemple, aux appels C # / c ++ gérés.