【问题标题】:Memory manager for cross DLL allocation/deallocation用于跨 DLL 分配/释放的内存管理器
【发布时间】:2013-05-06 14:41:11
【问题描述】:

已解决:经过几次实验后,这似乎是可能的。

我想知道是否有可能通过让内存管理器伴随重载内存函数(new、delete、delete[]、malloc()...)来避免常见的跨 dll 分配/释放问题并负责任何可以在程序的任何地方发生的分配/解除分配,从而确保一致性。

假设 a.dll 包含内存管理器,例如:

class EXPORT MemoryManager
{
    static void* Allocation( size_t uiSize );
    static void  Deallocation( void* pAllocated );
};

inline void* operator new( size_t uiSize )
{
    return MemoryManager::Allocation( uiSize );
}

inline void operator delete( void* pAllocated )
{
    MemoryManager::Deallocation( pAllocated );
}

以及其他任何地方,包括 b.dll:

int* piDummy = ExternalDllFunctionCallingNew();
delete piDummy;

能解决问题吗?

【问题讨论】:

  • 拥有内存管理器是问题的原因。每个模块都使用自己的。经典的做法是为 DLL 提供它自己的 CRT 版本。只要避免麻烦,编写不需要调用者释放内存的函数,而是将指针传递给缓冲区。
  • 看看Windows是如何处理资源的。例如。打开文件/关闭句柄。
  • @HansPassant 是的,我用 CRT 得到了那个东西。但是可以对任何指针进行指针解引用和指针复制。那么为什么我的 sn-p 不能保持一致性呢? Aka,我在哪里使用不同的 CRT ?我可能在这里没有完全清楚。我要说的是为什么我不能使用一个通用类来通过几个 dll 来分配/解除分配。因此使用相同的 CRT 堆管理器。
  • 好吧,你可以让它像那样工作。但是,如果您有能力强制每个 DLL 使用完全相同的内存管理器,那么您也有能力确保所有这些 DLL 使用完全相同的共享 CRT 版本。哪个是解决问题的更简单的方法。

标签: memory-management dll


【解决方案1】:

您可能误解了这个问题。问题不仅在于几个 DLL,还在于混合了不同的内存管理器。具体来说,当用于释放某个块的分配器与最初分配该块的分配器不同时,就会出现问题。一个常见问题是两个分配器期望不同的元数据布局(例如,块的大小存储在哪里)。您的“解决方案”只是添加了另一个内存管理器,因此它只会增加更多由不同内存管理器完成的分配和释放的可能性。 编辑: 如果你可以强制所有内存分配和释放使用你的内存管理器,它被限制在一个单独的 DLL 中,它可能只会工作美好的。但是,正如 Hans Passant 在 cmets 中指出的那样,如果您可以强制执行,您很可能也可以强制所有组件使用相同的 CRT 版本。

DLL 仅与此问题相关,因为大多数内存分配是通过 C 或 C++ 运行时提供的内存管理器进行的,并且根据 DLL 的运行方式,它们通常不同(甚至比其他运行时库更是如此)编译。如果您小心,您可以成功地跨 DLL 边界分配和解除分配,并且您可以在单个 DLL 中遇到类似的问题。

【讨论】:

  • 再一次,整个想法是始终使用相同的分配器/释放器。负责该任务的唯一实例将位于其中一个 dll 中。因此,我不明白为什么会出现问题。顺便说一句,我已经写了我正在谈论的内容,我很确定它正在工作,因为如果我不使用管理器,我的单元测试在堆验证上会失败。
  • @AdrianGoudard 假设 每个 分配都通过您的分配器。你能强制执行吗?我不会这么认为。
  • 是的,我可以强制执行,因为每个 STL 容器都必须使用我的自定义分配器/删除器,并且我正在监视对分配/解除分配函数的每次调用。
  • 好点。好吧,我有能力毫不费力地让所有事情都通过那个经理。但我想多线程 CRT 的性能会更好,对吧?
猜你喜欢
  • 2010-11-23
  • 2011-01-16
  • 2010-09-28
  • 2011-01-11
  • 1970-01-01
  • 1970-01-01
  • 2013-10-08
  • 2021-05-20
  • 2011-12-09
相关资源
最近更新 更多