É inacreditável a quantidade de informações enganosas que você pode ler nos artigos acima ...
E mesmo na documentação do microsoft msdn, o IsBadPtr foi banido. Muito bem - eu prefiro o aplicativo funcional em vez de travar. Mesmo que o prazo de trabalho possa estar funcionando incorretamente (desde que o usuário final possa continuar com o aplicativo).
Ao pesquisar no Google, não encontrei nenhum exemplo útil para janelas - encontrei uma solução para aplicativos de 32 bits,
http://www.codeproject.com/script/Content/ViewAssociatedFile.aspx?rzp=%2FKB%2Fsystem%2Fdetect-driver%2F%2FDetectDriverSrc.zip&zep=DetectDriverSrc%2FDetectDriver=%2Fsrrcppp&robtid.cc%2Fsrrcpp2FDetectDriver=%2Fsrttppp2Fdetc_pps2Fdetc%2Fdetc%2Fsrpps2Fdetc%2Fsrtt2Fdetc_2 = 2
mas também preciso oferecer suporte a aplicativos de 64 bits, portanto, esta solução não funcionou para mim.
Mas eu colhi os códigos-fonte do wine e consegui preparar um tipo de código semelhante que funcionaria para aplicativos de 64 bits também - anexando o código aqui:
#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 o código a seguir pode detectar se o ponteiro é válido ou não, você provavelmente precisará adicionar alguma verificação 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();
Isso obtém o nome da classe do ponteiro - acho que deve ser o suficiente para as suas necessidades.
Uma coisa que ainda temo é o desempenho da verificação de ponteiro - no fragmento de código acima, já existem 3-4 chamadas de API sendo feitas - pode ser um exagero para aplicativos de tempo crítico.
Seria bom se alguém pudesse medir a sobrecarga da verificação de ponteiro em comparação, por exemplo, com chamadas C # / c ++ gerenciado.