【发布时间】:2011-02-09 17:31:57
【问题描述】:
我有一个在 Windows 上泄漏的代码。它在许多 unix 平台上运行良好,并且泄漏仅发生在 Windows 上。 二进制文件由 exe、1 个 dll 和 2 个静态库组成。 exe 链接到 dll 和静态库,而静态库也链接到 dll。当由于某种原因调用标量删除析构函数而不是调用向量删除析构函数时,泄漏发生在 exe 代码中。这导致仅删除数组中的第一个对象,而数组的其余部分保留在内存中。
泄漏的伪代码如下所示:
class MyClassFromExe : public MyBaseClassFromDll {
public:
ClassFromDll* m_arr;
MyClassFromExe(unsigned int size)
{
m_arr = new ClassFromDll[size];
}
~MyClassFromExe()
{
delete [] m_arr;
}
};
void func()
{
MyClassFromExe obj(3);
}
当 func() 完成并调用析构函数时,我看到只有 m_arr 中第一个对象的析构函数被调用。从调试器我看到这是通过标量删除析构函数而不是向量删除析构函数完成的。这解释了为什么只有第一个对象被销毁。 我需要了解的是,为什么在使用delete []的时候会调用标量删除析构函数???
我找到了这个帖子 - Why is vector deleting destructor being called as a result of a scalar delete?。我遵循了那里的建议,并确保所有模块都使用 /MD 编译。
重要的是要注意,当包含 ClassFromDll 的 dll 是静态库而不是 dll 时,一切正常。仅当静态库更改为 dll 时才开始泄漏。 当程序在 Release 模式下泄漏时,它在 delete [] m_arr 上的 Debug 模式下崩溃。崩溃发生在 dbgdel.cpp 第 52 行 - _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)。
在 unix 平台上,这个库也是一个共享库,并且正如预期的那样,向量删除析构函数在那里被调用并且没有泄漏。问题可能出在VC编译器上吗?或者可能需要更改项目的其他一些设置? 我用的是VC2003。
提前谢谢你!
【问题讨论】:
-
我会调用那个数组。通常通过向量人的意思是
std::vector -
当它断言处于调试模式时,如果您在附加调试器后尝试执行“重试”,调用堆栈指向哪里?看起来你这里有堆损坏。
-
这可能与您的问题无关,但您为什么使用这么旧的编译器版本?
-
@Naveen - 当我尝试重试时,什么都没有发生,一切都只是挂起,直到我停止调试器。
-
@Andrey - 我写了向量删除析构函数,因为据我所知,这是编译器创建的用于删除数组的函数的名称。
标签: c++ vector debugging destructor memory-leaks