Sulit dipercaya betapa banyak informasi menyesatkan yang dapat Anda baca di artikel di atas ...
Dan bahkan dalam dokumentasi microsoft msdn IsBadPtr diklaim dilarang. Baiklah - Saya lebih suka aplikasi yang berfungsi daripada mogok. Bahkan jika jangka waktu bekerja mungkin tidak berfungsi dengan benar (selama pengguna akhir dapat melanjutkan aplikasi).
Dengan googling, saya belum menemukan contoh berguna untuk windows - menemukan solusi untuk aplikasi 32-bit,
http://www.codeproject.com/script/Content/ViewAssociatedFile.aspx?rzp=%2FKB%2Fsystem%2Fdetect-driver%2F%2FDetectDriverSrc.zip&zep=DetectDriverSrc%2FDetectDriver%2FsRc%2Ftcidp2 = 2
tetapi saya juga perlu mendukung aplikasi 64-bit, jadi solusi ini tidak berhasil untuk saya.
Tapi saya telah memanen kode sumber anggur, dan berhasil memasak jenis kode serupa yang akan berfungsi untuk aplikasi 64-bit juga - dengan melampirkan kode di sini:
#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;
}
Dan kode berikut dapat mendeteksi apakah pointer valid atau tidak, Anda mungkin perlu menambahkan beberapa pemeriksaan NULL:
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();
Ini mendapat nama kelas dari pointer - Saya pikir itu harus cukup untuk kebutuhan Anda.
Satu hal yang saya masih khawatirkan adalah kinerja pemeriksaan penunjuk - di snipet kode di atas sudah ada 3-4 panggilan API yang dibuat - mungkin berlebihan untuk aplikasi kritis waktu.
Akan lebih baik jika seseorang dapat mengukur overhead pemeriksaan pointer dibandingkan, misalnya dengan panggilan C # / managed c ++.