Visual C++ Runtime
跳到导航
跳到搜索
由于不能将标准C++运行时链接到内核,所以需要几个函数来替换它的功能。 本文提供有关如何为Visual C++编译器实现你自己的C++运行库的信息。
调用全局静态变量的构造函数
这段代码将有助于调用全局静态变量的所有构造函数。
// 构造函数原型
typedef void (__cdecl *_PVFV)(void);
typedef int (__cdecl *_PIFV)(void);
// 链接器将构造函数放在这些部分之间,我们使用它们来定位构造函数指针。
#pragma section(".CRT$XIA",long,read)
#pragma section(".CRT$XIZ",long,read)
#pragma section(".CRT$XCA",long,read)
#pragma section(".CRT$XCZ",long,read)
//将.CRT数据放入.rdata节
#pragma comment(linker, "/merge:.CRT=.rdata")
// 围绕构造函数的指针
__declspec(allocate(".CRT$XIA")) _PIFV __xi_a[] = { 0 };
__declspec(allocate(".CRT$XIZ")) _PIFV __xi_z[] = { 0 };
__declspec(allocate(".CRT$XCA")) _PVFV __xc_a[] = { 0 };
__declspec(allocate(".CRT$XCZ")) _PVFV __xc_z[] = { 0 };
extern __declspec(allocate(".CRT$XIA")) _PIFV __xi_a[];
extern __declspec(allocate(".CRT$XIZ")) _PIFV __xi_z[]; // C初始化器
extern __declspec(allocate(".CRT$XCA")) _PVFV __xc_a[];
extern __declspec(allocate(".CRT$XCZ")) _PVFV __xc_z[]; // C++初始化器
// 调用C构造函数
static int _initterm_e(_PIFV * pfbegin, _PIFV * pfend) {
int ret = 0;
// 从下到上遍历函数指针表,直到
// 遇到结尾。不要跳过第一个条目。初始
// pfbegin的值指向第一个有效条目。不要试图
// 执行pfend指向的内容。只有pfend之前的条目才有效。
while ( pfbegin < pfend && ret == 0)
{
//如果当前表项非空,则通过它进行调用
if ( *pfbegin != 0 )
ret = (**pfbegin)();
++pfbegin;
}
return ret;
}
// 调用C构造函数
static void _initterm (_PVFV * pfbegin, _PVFV * pfend)
{
// 从下到上遍历函数指针表,直到
// 遇到结尾。不要跳过第一个条目。初始
// pfbegin的值指向第一个有效条目。不要试图
// 执行pfend指向的内容。只有pfend之前的条目才有效。
while ( pfbegin < pfend )
{
//如果当前表项非空,则通过它进行调用
if ( *pfbegin != 0 )
(**pfbegin)();
++pfbegin;
}
}
// 尽快调用此函数。基本上应该是你现在
// 就要跳转到C/C++内核中。但请记住,内核尚未初始化,
// 而且你不能在构造函数中使用很多东西!
bool CallConstructors() {
// 执行C初始化
int initret = _initterm_e(__xi_a, __xi_z);
if ( initret != 0 ) {
return false;
}
// 执行C++初始化
_initterm(__xc_a, __xc_z);
return true;
}
new和delete运算符
你首先要做的事情之一就是实现new和delete运算符。 一开始,你还不能真正实现它们,只需要有它们的存根。 稍后,当你的内存管理器工作时,你可以完全实现它们。 下面是存根:
void* __cdecl operator new(size_t size)
{
// 分配内存
return 0;
}
void* __cdecl operator new[](size_t size)
{
// 分配内存
return 0;
}
void __cdecl operator delete(void *p)
{
if (p == 0) {
return;
}
// 释放分配的内存
}
void __cdecl operator delete[](void *p)
{
if (p == 0) {
return;
}
// 释放分配的内存
}
如果你想要使用placement new(定位放置new),则需要将以下实现放入一个头文件中,并在需要时将其包括在内。
inline void* __cdecl operator new(size_t size, void* address)
{
return address;
}