Thật không thể tin được là bạn có thể đọc được bao nhiêu thông tin sai lệch trong các bài báo trên ...
Và ngay cả trong tài liệu msdn của microsoft, IsBadPtr được cho là bị cấm. Ồ, tôi thích ứng dụng đang hoạt động hơn là bị treo. Ngay cả khi thời hạn làm việc có thể hoạt động không chính xác (miễn là người dùng cuối có thể tiếp tục với ứng dụng).
Bằng cách sử dụng googling, tôi không tìm thấy bất kỳ ví dụ hữu ích nào cho windows - đã tìm thấy giải pháp cho các ứng dụng 32 bit,
http://www.codeproject.com/script/Content/ViewAssociatedFile.aspx?rzp=%2FKB%2Fsystem%2Fdetect-driver%2F%2FDetectDriverSrc.zip&zep=DetectDriverSrc%2FDetectDriver%2Fsrc%2Fdtid295&obID = 2
nhưng tôi cũng cần hỗ trợ các ứng dụng 64-bit, vì vậy giải pháp này không phù hợp với tôi.
Nhưng tôi đã thu thập mã nguồn của rượu vang và quản lý để nấu loại mã tương tự cũng sẽ hoạt động cho các ứng dụng 64 bit - đính kèm mã ở đây:
#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;
}
Và mã sau có thể phát hiện xem con trỏ có hợp lệ hay không, bạn có thể cần thêm một số kiểm tra 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();
Điều này nhận được tên lớp từ con trỏ - Tôi nghĩ nó sẽ đủ cho nhu cầu của bạn.
Một điều mà tôi vẫn sợ là hiệu suất của việc kiểm tra con trỏ - trong đoạn mã ở trên, đã có 3-4 lệnh gọi API được thực hiện - có thể quá mức cần thiết cho các ứng dụng quan trọng về thời gian.
Sẽ rất tốt nếu ai đó có thể đo lường chi phí kiểm tra con trỏ so với ví dụ: với C # / các cuộc gọi c ++ được quản lý.