0

COM+ 应用程序,在 Windows XP SP 3 上使用 MS Visual Studio 6、SP 6 构建,以及远程调试。

我的主要问题是这个;如果我可以进入“删除”,为什么我无法进入“新”?我主要是在寻找关于我应该研究什么的想法。

我正在做一个我刚刚熟悉的相当大的项目。当前的问题是堆损坏问题,其中发布版本最终会耗尽其工作集并崩溃。这个问题是如此普遍,以至于下面的代码会破坏堆:

int * iArray = new int [100];
delete [] iArray;

我说“损坏堆”是因为调试输出在“删除”上显示“heap [dllhost.exe]:指定给 rtlvalidateheap 的地址无效”。

我可以很好地进入“删除”调用,它似乎正在调用正确的调用(位于 ...\Microsoft Visual Studio\VC98\CRT\SRC 中的 DELOP.cpp 中)但是,无论出于何种原因,我都无法进入任何对“新”的调用。我在这里抓住了稻草,但我感觉代码库中的某个地方有人覆盖了“新”运算符,而我正在查看的代码无意中使用了它。发布版本的症状似乎是内存被分配给一个堆并试图从另一个堆中删除,至少这是我的预感。

编辑:确认!对不起大家,我发布得太早了,应该提供更多信息。

我搜索了代码库并找到了一些覆盖,但它们都在类中,而不是全局定义的。唯一不在类中的是以下内容:

struct _new_selector 
{

};

inline void* operator new(size_t, void *ptr, _new_selector)
{
    return (ptr); 
}

但这是一个新的展示位置,我很确定在这种情况下它不算数。对于原始的“新”,我应该进入什么库?我猜它与“删除”相同,但如果不是,也许我只是没有调试信息?

编辑2:搞砸这个我发现在调试版本中这个问题不存在。我已经查看了运行时库,它使用 /MD 和 /MDd 进行调试。不仅如此,我还使用 /MDd jut 构建了发布版本,以确保仍然没有任何变化。查看调试版本和发布版本的地图,新操作员(带有它的修饰)如下:

释放:

0001:00061306 ??2@YAPAXI@Z 10062306 f MSVCRTD:MSVCRTD.dll

0002:00000298 _imp ?? 2@YAPAXI@Z 1006e298 MSVCRTD:MSVCRTD.dll

调试:

0001:00077d06 ??2@YAPAXI@Z 10078d06 f MSVCRTD:MSVCRTD.dll

0004:00000ad4_imp ??2@ YAPAXI @Z 100b5ad4 MSVCRTD:MSVCRTD.dll

我还检查了删除运算符:

释放:

0001:000611f0 ??3@YAXPAX@Z 100621f0 f msvcprtd:delop_s.obj

调试:

0001:00077bf0 ??3@YAXPAX@Z 10078bf0 f msvcprtd:delop_s.obj

另外,我没有打印出来,但如果有帮助,我可以得到它,新运算符的反汇编在发布和调试中看起来是一样的。所以我想这不是覆盖?运算符的内联覆盖会使这不正确吗?

此外,作为一个产生多个 dllhost.exe 进程的 COM+ 应用程序,对 new 运算符的调用是否可以转到另一个 DLL 或 exe,而对删除的调用是否可以转到相反的位置?

4

2 回答 2

3

根据您的预感,代码中可能存在重载的新内容,您可以检查的东西很少

  1. 反汇编代码并找出该文件中的库名称,通常程序集中有一些东西会给你一个提示
  2. 如果您无法找到库名称,请检查您正在输入的程序集中的地址。然后在调试输出窗口中,检查各种库的加载地址 - 这可以为您提供关于要检查哪个库的线索
  3. 如果以上没有帮助,请检查您是否可以为整个项目生成地图文件。如果可以,那么您可以在地图文件中查找地址,这可能会有所帮助
  4. 尝试使用运行时库的调试版本。不记得打开 debug_malloc 的选项是什么。这可以帮助您弄清楚堆上发生了什么

社区可以添加更多我可能错过的内容。最后,如果您确实解决了问题,请分享您是如何解决的。在这里或作为您博客的链接。处理大型项目的堆问题通常并不容易,我们都可以学习一两个新技巧。

于 2012-03-07T16:01:14.287 回答
2

好的,这就是它最终的样子。

我正在做的这个项目有大约三十个左右的项目。有些创建库,有些创建 dll,还有一些创建 exe。无论如何,这一切都是交织在一起的。再加上我们使用 ATL 和 COM 的事实,它很快就开始变得疯狂。最终结果是,一些(并非全部)项目是使用 _ATL_MIN_CRT 编译器定义构建的,即使这是一个桌面应用程序,而不是客户端需要下载一些模块的基于 Web 的应用程序。

以下是关于 _ATL_MIN_CRT 的一些信息:

http://support.microsoft.com/default.aspx?scid=kb;EN-US;q166480

http://msdn.microsoft.com/en-us/library/y3s1z4aw%28v=vs.80%29.aspx

请注意,从第一个链接开始,这也将消除内存分配例程的使用。我不确定使用它的最初动机是什么,或者它是否真的是故意的,但它肯定会导致分配内存的问题。此外,这只影响发布版本,因此很难找到它。

基本上,模块 A 是使用 _ATL_MIN_CRT 构建的,而模块 B 是在没有它的情况下构建的,但对模块 A 有依赖关系。由于这也使用 COM 并且所有内容都在 dllhost.exe 中运行,因此当模块 B 尝试使用 new 运算符时,它似乎已从其 dll 中尝试在堆上分配内存。然后,当调用 delete 时,它​​试图在其 dll 中删除它。因此,我们有一个疯狂的内存泄漏。

请注意,删除 _ATL_MIN_CRT 可以解决此问题,但我上面提到的只是我对它的理解。它可能更复杂/更简单,但无论如何,这就是问题所在。

感谢大家的建议,他们确实帮我找到了这个东西!

于 2012-03-20T17:43:50.830 回答