C/C++ 的 new 调用 “::operator new” 函数进行内存分配,delete 调用 “::operator delete” 函数,但我们现在要做的是在不影响应用代码前提下替换其 “C/C++” 内存的分配与释放。
我们先琢磨大概有哪些实现,很多人们可能会考虑到通过 “inline-hook”,这是可行的,只需要拿到这几个由编译器内置的 “new、delete” 的函数地址就可以,当然还有另一种有效的办法;
union
{
void*(__CRTDECL* operator_new_proc)(size_t _Size);
void* operator_new_ptr;
} u1;
u1.operator_new_proc = ::operator new;
printf("0x%02llx", (__int64)u1.operator_new_ptr);
return getchar();
我们可以通过上面的办法获取到 “::operator new” 的函数地址,顺带一提 “::operator new” 函数被编译器实现了不同的重载,在Take 相应的函数地址的时候,必须提供清晰准确的函数类型指针。
那么拿到函数地址以后,我们就可以在由编译器实现函数上面,打上JMP,桥接C/C++内存分配与释放的处理,那么小小的琢磨琢磨,那么我们还需要很蹩脚的专门搞一套 “内存分配与释放的宏”?例:__new、__delete 的宏,仅仅只是为了替代由编译器实现的 “new、delete” 的内存分配与释放的功能(移入应用内内存池),当然还有调用 “类” 的实例的析构函数。
C/C++ Placement New 分配它似乎有用但又没有用,它的确可以 “从任何一块固定的内存中” 分配类的实例,例:我们从LocalHeap 中利用 LocalAlloc 分配了一块内存,利用 Placement New 进行分配,那么调用 delete 释放是不可的,虽然它正确的调用了相应的析构函数,那么既然通过 Placement New 进行分配的方式具有这样的固有缺陷,那应该怎么办?上面提到了定义 __new、__delete 的宏。
上面本人提到还有一种不利用 “inline-hook” 的办法,这种办法是利用 C/C++ 编译器的特性完成的,它并不需要进行任何可见形式的 “inline-hook”,我们知道在 “C/C++ 编译器” 的编译规则中采取一种 “就近原则” 的思路,而我们要利用的办法就是这样的,但有些可惜的是 “它必须定义在 C/C++ 源文件内【不可头文件,C/C++ 语言各个平台都实现了相应的头文件,hpp-> vcruntime_new.h】”,由连接器自动内链,若不可将自动链接由编译器内置的函数,好比你可以通过类似的办法替换 “x86(i386)” CXX 编译器关于 “long long” 的乘法计算函数的实现,“__allmul” 函数(位于:llmul.asm 文件内)。
#ifndef CXXLANGMEMORY_ALLOCATOR_IMPLEMENT
#define CXXLANGMEMORY_ALLOCATOR_IMPLEMENT
_Ret_notnull_ _Post_writable_byte_size_(_Size)
extern _VCRT_ALLOCATOR void* __CRTDECL operator new(
size_t _Size
) throw()
{
if (_Size <= 0)
{
return NULL;
}
return (void*)nvm::gc::mempoll::Alloc(_Size);
}
extern void __CRTDECL operator delete(
void* _Block
) throw()
{
if (_Block != NULL)
{
nvm::gc::mempoll::Free((nvm::IntPtr)_Block);
}
}
extern void __CRTDECL operator delete(
void* _Block,
size_t _Size
) throw()
{
if (_Size > 0)
{
::operator delete(_Block);
}
}
_Ret_notnull_ _Post_writable_byte_size_(_Size)
extern _VCRT_ALLOCATOR void* __CRTDECL operator new[](
size_t _Size
) throw()
{
return ::operator new(_Size);
}
extern void __CRTDECL operator delete[](
void* _Block,
size_t _Size
) throw()
{
return ::operator delete(_Block, _Size);
}
#endif