Es ist unglaublich, wie viele irreführende Informationen Sie in den obigen Artikeln lesen können ...
Und selbst in der Microsoft MSDN-Dokumentation wird behauptet, IsBadPtr sei verboten. Na ja - ich arbeite lieber mit einer Anwendung als mit einem Absturz. Auch wenn das Arbeiten mit Begriffen möglicherweise nicht ordnungsgemäß funktioniert (solange der Endbenutzer mit der Anwendung fortfahren kann).
Durch Googeln habe ich kein nützliches Beispiel für Windows gefunden - eine Lösung für 32-Bit-Apps gefunden,
http://www.codeproject.com/script/Content/ViewAssociatedFile.aspx?rzp=%2FKB%2Fsystem%2Fdetect-driver%2F%2FDetectDriverSrc.zip&zep=DetectDriverSrc%2FDetectDriver%2Fsrctt2 = 2
Ich muss aber auch 64-Bit-Apps unterstützen, sodass diese Lösung bei mir nicht funktioniert hat.
Aber ich habe die Quellcodes von Wein geerntet und es geschafft, einen ähnlichen Code zu erstellen, der auch für 64-Bit-Apps funktioniert - Code hier anhängen:
#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;
}
Wenn der folgende Code erkennt, ob der Zeiger gültig ist oder nicht, müssen Sie wahrscheinlich eine NULL-Prüfung hinzufügen:
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();
Dies erhält den Klassennamen vom Zeiger - ich denke, es sollte für Ihre Bedürfnisse ausreichen.
Eine Sache, die ich immer noch befürchte, ist die Leistung der Zeigerprüfung - im obigen Code-Snipet werden bereits 3-4 API-Aufrufe ausgeführt -, die für zeitkritische Anwendungen möglicherweise zu viel des Guten sind.
Es wäre gut, wenn jemand den Overhead der Zeigerprüfung im Vergleich zu beispielsweise C # / verwalteten C ++ - Aufrufen messen könnte.