Yukarıdaki makalelerde ne kadar yanıltıcı bilgi okuyabileceğiniz inanılmaz ...
Ve hatta microsoft msdn belgelerinde IsBadPtr'in yasaklandığı iddia ediliyor. Oh peki - çökmek yerine çalışan uygulamayı tercih ederim. Terim çalışması yanlış çalışıyor olsa bile (son kullanıcı uygulamaya devam edebildiği sürece).
Google'da pencereler için yararlı bir örnek bulamadım - 32 bit uygulamalar için bir çözüm buldum,
http://www.codeproject.com/script/Content/ViewAssociatedFile.aspx?rzp=%2FKB%2Fsystem%2Fdetect-driver%2F%2FDetectDriverSrc.zip&zep=DetectDriverSrc%2FDetectDriver%2Fsrc%2FdrvCppid95 = 2
ancak 64 bit uygulamaları da desteklemem gerekiyor, bu yüzden bu çözüm benim için işe yaramadı.
Ancak, wine kaynak kodlarını topladım ve 64 bit uygulamalar için de işe yarayacak benzer türde bir kod hazırlamayı başardım - kodu buraya ekleyerek:
#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;
} 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
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;
}
Ve aşağıdaki kod, işaretçinin geçerli olup olmadığını algılayabilir, muhtemelen bazı NULL denetimi eklemeniz gerekir:
CTest* t = new CTest();
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();
Bu, sınıf adını göstericiden alır - ihtiyaçlarınız için yeterli olması gerektiğini düşünüyorum.
Hala korktuğum bir şey, işaretçi kontrolünün performansı - yukarıdaki kod parçacığında zaten 3-4 API çağrısı yapılıyor - zaman açısından kritik uygulamalar için aşırı olabilir.
Örneğin, C # / yönetilen c ++ çağrılarına kıyasla işaretçi kontrolünün ek yükünü ölçebilmesi iyi olur.