在任何全局对象

时间:2015-05-31 15:19:28

标签: c++ dll global-variables

我正在编写一个C ++内存分析器。

众所周知,可执行程序可能包含许多全局对象, 它的DLL模块可能包含全局对象 好。这些全局对象将使用CRT进行初始化 初始化 - 在入口点之后和WinMain之前;对于DLL, 在你进入DllMain之前,入口点是_DllMainCRTStartup, DLL的所有全局对象都被初始化。

全局对象可以分配内存。所以一个内存分析器 必须在任何全局对象初始化之前初始化。后 做了很多研究,我发现这不是一件容易的事。

一个想法是使用带有CREATE_SUSPENDED标志的CreateProcess - 尝试 获得第一次机会。之后,使用CreateRemoteThread进行调用 LoadLibrary在目标进程中加载​​一个注入DLL,和 初始化该DLL。但它不起作用because this will load all the implicit-linking DLLs of the executable program first.也许CreateRemoteThread触发了这种行为?

那么,我们如何获得第一次机会?

1 个答案:

答案 0 :(得分:0)

除非使用特定于平台的方式,否则可能有一种方法可以做到这一点,但解决问题的一种方法是将延迟初始化与dylib加载相结合。

例如,假设你的内存分配器函数是这样导出的:

attribute disable

...在名为API void* exported_alloc(); API void exported_free(void* mem); 的dylib内。

在这种情况下,为了确保所有其他dylib在加载时都可以访问它,我们可以创建一个中央静态链接的库(例如:sdk.lib)您的dylib链接与标题如下:

mem.dll

......我们可以像这样实施:

#ifndef MEMORY_H
#define MEMORY_H

// Memory.h
void* my_alloc();
void my_free(void* mem);

#endif

..然后在完成DLL后的适当时间调用static void* (exported_alloc)() = 0; static void (exported_free)(void* mem) = 0; static void initialize() { if (!exported_alloc) { // Load 'mem.dll' (ex: 'LoadLibrary') and look up // symbols for `exported_alloc` and `exported_free` // (ex: GetProcAddress). } } void* my_alloc() { initialize(); return exported_alloc(); } void my_free(void* mem) { initialize(); exported_free(mem); } 。这会产生一些运行时开销(类似于访问单例的开销),但它是一个跨平台的解决方案(前提是您有一个跨平台的方法在运行时加载/卸载dylibs /共享库)。 / p>

使用此解决方案,所有在全局范围内分配内存的DLL将在以惰性初始化方式执行任何内存分配之前加载FreeLibrary,确保它们都可以访问您的内存函数在适当的时候。