C ++ - 在调试期间无法使用'new'运算符

时间:2012-03-07 15:49:13

标签: c++ new-operator visual-studio-6

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

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

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

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

我说'损坏了堆',因为调试输出在'delete'上显示“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,并且调用delete会转到相反的位置?

2 个答案:

答案 0 :(得分:3)

在你的预感中,代码中可能存在一个超载的新内容,你可以检查的东西很少

  1. 反汇编代码并找出该文件中的库名,通常程序集中有一些内容会给你一个提示
  2. 如果您无法找到库名称,请检查您输入的程序集中的地址。然后在调试输出窗口中,检查各种库的加载地址 - 这可以为您提供关于要检查的库的线索
  3. 如果上述方法无效,请检查您是否可以为整个项目生成地图文件。如果可以,那么您可以在地图文件中查找地址,这可能会有所帮助
  4. 尝试使用运行时库的调试版本。无法重新选择将打开debug_malloc的选项。这可以帮助你弄清楚堆上发生了什么
  5. 社区可以添加一些我可能错过的内容。最后,如果你确实解决了这个问题,请分享你是如何做到的。在这里或作为您博客的链接。处理大型项目的堆问题通常并不容易,我们都可以学习一两个新技巧。

答案 1 :(得分:2)

好的,所以这就是最终的结果。

我正在制作的计划中有大约三十个左右的项目。有些人创建了libs,有些是dll,还有其他人。无论如何,它都是混合在一起的。再加上我们使用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可以解决这个问题,但我上面提到的只是我对它的理解。它可能更多/更少复杂,但无论如何,这都是问题。

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