È incredibile quante informazioni fuorvianti puoi leggere negli articoli sopra ...
E anche nella documentazione di microsoft msdn si afferma che IsBadPtr è stato bandito. Vabbè, preferisco l'applicazione funzionante piuttosto che il crash. Anche se il termine di lavoro potrebbe non funzionare correttamente (a condizione che l'utente finale possa continuare con l'applicazione).
Cercando su Google non ho trovato alcun esempio utile per Windows: ho trovato una soluzione per app a 32 bit,
http://www.codeproject.com/script/Content/ViewAssociatedFile.aspx?rzp=%2FKB%2Fsystem%2Fdetect-driver%2F%2FDetectDriverSrc.zip&zep=DetectDriverSrc%2FDetectDriver%2FsrobtF2Fsrcid2Fsrcid2Frpidtc&hl=it = 2
ma devo anche supportare le app a 64 bit, quindi questa soluzione non ha funzionato per me.
Ma ho raccolto i codici sorgente del vino e sono riuscito a cucinare un tipo simile di codice che funzionerebbe anche per le app a 64 bit, allegando il codice qui:
#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;
}
E il codice seguente può rilevare se il puntatore è valido o meno, probabilmente è necessario aggiungere un controllo 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();
Questo ottiene il nome della classe dal puntatore: penso che dovrebbe essere sufficiente per le tue esigenze.
Una cosa di cui ho ancora paura sono le prestazioni del controllo del puntatore - nel codice cecchino sopra ci sono già 3-4 chiamate API in corso - potrebbe essere eccessivo per applicazioni critiche in termini di tempo.
Sarebbe utile se qualcuno potesse misurare il sovraccarico del controllo del puntatore rispetto, ad esempio, alle chiamate C # / c ++ gestite.