与静态 c 运行时链接时内存分配/解除分配的问题

Suh*_*has 2 c c++ visual-c++

我在 Jeffrey Richter 和 Christophe Nasarre 合着的 Windows via C-C++ 一书中遇到了下面的注释。

检查以下代码:V

OID EXEFunc() {
PVOID pv = DLLFunc();
// Access the storage pointed to by pv...
// Assumes that pv is in EXE's C/C++ run-time heap
free(pv);
}
PVOID DLLFunc() {
// Allocate block from DLL's C/C++ run-time heap
return(malloc(100));
}
Run Code Online (Sandbox Code Playgroud)

所以你怎么看?前面的代码是否正常工作?DLL 的函数分配的块是否被 EXE 的函数释放?答案是:也许。显示的代码没有为您提供足够的信息。如果 EXE 和 DLL 都链接到 DLL C/C++ 运行时库,则代码工作正常。但是,如果一个或两个模块链接到静态 C/C++ 运行时库,则对 free 的调用将失败。

我无法理解为什么在将模块与静态 C 运行时链接时调用 free 会失败。

有人可以解释为什么免费失败吗?在这里找到了类似的问题: C 运行时静态与动态链接中的内存分配

但我和 MrPhilTx 有同样的疑问:难道所有的堆都在同一个地址空间中吗?

谢谢!

Fox*_*ter 6

当您的 DLL 和 EXE 都静态链接到 C 运行时,这两个运行时根本不知道彼此。因此,EXE 和 DLL 都有自己的运行时副本、自己的堆和堆元数据。双方都不知道其他元数据,并且在释放内存时没有安全的方法来更新数据。你最终会得到不稳定的元数据,事情最终会失败(如果你很幸运,它会立即失败)。

这意味着您的进程中最终至少有两个堆,每个堆都有自己的规则和元数据。EXE 无法知道 DLL 分配内存的确切方式,因此无法释放它。

至于为什么当所有东西都是动态链接的时候,你可以逃避共享一个堆,这很简单,进程中只有一个 C 运行时 DLL 的副本,所以如果每个 DLL 都链接到它,它们都会调用相同的代码相同的元数据。

  • 即使链接到 EXE 和 DLL 的运行时代码相同,元数据的单独副本这一事实也会把一切搞砸。在一个堆上分配并释放到另一个堆将导致大混乱。 (2认同)