导读
开发环境
| 版本号 | 描述 | |
|---|---|---|
| 文章日期 | 2022-11-09 | |
| 操作系统 | Win11-21H2 | 内部版本号22000.588 |
| Visual Studio 2019 | 16.11.12 | |
编写代码实现
效果

代码实现
#pragma once
#include <windows.h>
struct TypeDescriptor
{
DWORD ptrToVTable;
DWORD spare;
char name[1];
};
struct PMD
{
int mdisp; //member displacement
int pdisp; //vbtable displacement
int vdisp; //displacement inside vbtable
};
struct RTTIBaseClassDescriptor
{
struct TypeDescriptor* pTypeDescriptor; //type descriptor of the class
DWORD numContainedBases; //number of nested classes following in the Base Class Array
struct PMD where; //pointer-to-member displacement info
DWORD attributes; //flags, usually 0
};
struct RTTIClassHierarchyDescriptor
{
DWORD signature; //always zero?
DWORD attributes; //bit 0 set = multiple inheritance, bit 1 set = virtual inheritance
DWORD numBaseClasses; //number of classes in pBaseClassArray
struct RTTIBaseClassArray* pBaseClassArray;
};
typedef RTTIClassHierarchyDescriptor* PRTTIClassHierarchyDescriptor;
struct RTTICompleteObjectLocator
{
DWORD signature; //always zero ?
DWORD offset; //offset of this vtable in the complete class
DWORD cdOffset; //constructor displacement offset
struct TypeDescriptor* pTypeDescriptor; //TypeDescriptor of the complete class
struct RTTIClassHierarchyDescriptor* pClassHierarchyDescriptor; //describes inheritance hierarchy
};
typedef RTTICompleteObjectLocator* PRTTICompleteObjectLocator;
namespace my
{
DWORD ReadDword32(PVOID obj)
{
return *(PDWORD)obj;
}
DWORD ReadDword32(DWORD obj)
{
return *(PDWORD)obj;
}
// vtable 地址
DWORD GetVTableByObj(PVOID obj)
{
return ReadDword32(obj);
}
// RTTICompleteObjectLocator
// vtable - 4
PRTTICompleteObjectLocator GetRttiColByObj(PVOID obj)
{
return (PRTTICompleteObjectLocator)ReadDword32(GetVTableByObj(obj) - 4);
}
// 获取虚函数对象的类名
char* GetObjectClassName(PVOID obj)
{
PRTTICompleteObjectLocator pCol = GetRttiColByObj(obj);
return pCol->pTypeDescriptor->name;
}
}
测试代码
class CFu
{
public:
CFu(): a(1), b(2) {}
int a;
int b;
};
class CZi2 : public CFu
{
public:
CZi2() : a(3), c(4) {}
// 类中必须包含虚函数
virtual ~CZi2() {};
int a;
int c;
};
void foobar()
{
CZi2 zi;
char* className = my::GetObjectClassName(&zi);
MyLogD("className = %s \n", className);
// std::string不包含虚函数,下面代码会崩溃
std::string s;
char* className2 = my::GetObjectClassName(&s);
MyLogD("className2 = %s \n", className2);
}
原理
参考下面的图,表示了RTTI的数据结构
参考资料
- 运行时类型信息 https://zh.m.wikipedia.org/zh-hans/%E5%9F%B7%E8%A1%8C%E6%9C%9F%E5%9E%8B%E6%85%8B%E8%A8%8A%E6%81%AF
- Visual C++ RTTI Inspection https://blog.quarkslab.com/visual-c-rtti-inspection.html
- qq群:夜猫逐梦技术交流裙/953949723

**ps:**文章中内容仅用于技术交流,请勿用于违规违法行为。


5360

被折叠的 条评论
为什么被折叠?



