我们有一个用Visual Basic 6.0编写的前端,它调用混合C/C++编写的几个后端DLL。问题是每个DLL似乎都有自己的堆,其中一个不够大。当我们分配了足够的内存时,堆会与程序堆栈发生冲突。 除了用C++编写的基本DLL封装外,每个DLL都完全用C语言编写。每个DLL都有一些入口点。每个入口点立即调用一个C例程。我们希望增加DLL中堆的大小,但一直未能弄清楚如何做到这一点。我搜索了指导,并发现这些MSDN文章:如何在混合语言应用程序中创建堆?
http://msdn.microsoft.com/en-us/library/hh405351(v=VS.85).aspx
这些文章很有意思,但提供了矛盾的信息。在我们的问题中,似乎每个DLL都有自己的堆。这与“堆:乐趣和痛苦”文章相匹配,文章说C启动时(C RT)库在启动时创建了自己的堆。 “管理堆内存”文章指出,C RT库分配在默认进程堆外。 “Win32中的内存管理选项”文章说这种行为取决于正在使用的C RT库的版本。
我们通过从私有堆中分配内存来暂时解决了这个问题。但是,为了改进这个非常大型的复杂程序的结构,我们希望从一个C++包装器切换到真正的具有类的C++。我们非常肯定,新的自由操作符不会从我们的私有堆中分配内存,我们想知道如何控制C++在每个DLL中分配对象时使用的堆的大小。该应用程序需要从2000年到7
问题在桌面Windows-NT的所有版本中运行,
任何人都可以带我们去明确和正确的文件是 讲解了如何控制规模堆C++用来分配 对象?
有几个人声称由堆分配覆盖堆栈造成的堆栈损坏是不可能的。这是我们观察到的。 VB前端使用它动态加载的四个DLL。每个DLL独立于其他DLL并提供前端调用的一些方法。所有的DLL通过写入磁盘文件的数据结构进行交流。这些数据结构都是静态构造的。它们不包含指针,只是值类型和固定大小的值类型数组。问题DLL由文件名传递的单个调用调用。它旨在分配完成处理所需的大约20MB数据结构。它做了很多计算,将结果写入磁盘,释放20MB的数据结构,并返回和错误代码。然后前端卸载DLL。在调试讨论中的问题时,我们在数据结构分配代码的开头设置了一个断点,并观察calloc调用返回的内存值,并将它们与当前的堆栈指针进行比较。我们看着分配的块接近堆栈。分配完成后,堆栈开始增长,直到堆栈重叠。最终计算结果写入了堆并损坏了堆栈。随着堆栈解开,它试图返回到一个无效地址并且因分段错误而崩溃。
我们的每个DLL都静态链接到CRT,这样每个DLL都有自己的CRT堆和堆管理器。微软在http://msdn.microsoft.com/en-us/library/ms235460(v=vs.80).aspx中说:
CRT库的每个副本都有一个单独的不同的状态。 因此,诸如文件句柄,环境变量和 语言环境的CRT对象仅对分配或设置了这些对象的CRT副本有效。当DLL及其用户使用CRT库的不同副本时,无法将这些CRT对象跨越DLL边界 传递,并期望它们在另一端正确拾取。
另外,因为CRT库的每个副本都有自己的堆管理器,所以在一个CRT库中分配内存并将指针穿过 DLL边界,并由另一个CRT库的副本释放,这是 的潜在原因堆腐败。
我们不通过DLL之间的指针。我们没有遇到堆腐败,我们遇到堆栈损坏。
希望你得到一个正确的答案,但如果你不这样做,你总是可以覆盖'new'和'delete'运算符来处理一个私有堆。 –
谢谢。我知道我们可以做到这一点,但这是一个相当复杂的解决方案。如果我们能够计算出如何去做,那么增加运行时提供的堆的大小就简单多了。我们只使用私人堆,因为我们还没有弄清楚这一点。 –
碰撞是不可能的。请澄清。 –