std :: string构造函数中的内存分配/堆损坏

时间:2011-07-02 15:08:00

标签: c++ memory-management

我再次遇到内存分配方面的问题,我无法弄清楚原因。

当我在调试模式下运行程序时,我收到以下错误消息(我试图尽可能准确地翻译它):

Windows在LogoColorDetector.exe中触发了断点。这可能是由堆损坏引起的,这表示LogoColorDetector.exe或其中一个加载的DLL [...]

中存在问题

当我调试程序时,我发现问题似乎发生在以下行:

std::string tmp = imgTrain2[j]->getFilepath();

getFilepath() - 函数实现如下:

const std::string& support::Image::getFilepath() const
{
    return this->_filePath;
}

我已经检查过imgTrain [j]中的Image对象是否有正确的_filePath字符串。所以我认为问题出在其他地方。有趣的是,包含有问题的行的功能似乎有效。这是我第二次调用它失败的函数,这表明问题不在函数本身。我没有分配任何内存,也没有删除函数中的任何内容,除了可能通过std :: string

间接完成的内容

如果它是任何人的帮助,这里是堆栈跟踪:

msvcr100d.dll!_heap_alloc_base(unsigned int size)  Zeile 55 C
msvcr100d.dll!_heap_alloc_dbg_impl(unsigned int nSize, int nBlockUse, const char * szFileName, int nLine, int * errno_tmp)  Zeile 431 + 0x9 Bytes   C++
msvcr100d.dll!_nh_malloc_dbg_impl(unsigned int nSize, int nhFlag, int nBlockUse, const char * szFileName, int nLine, int * errno_tmp)  Zeile 239 + 0x19 Bytes   C++
msvcr100d.dll!_nh_malloc_dbg(unsigned int nSize, int nhFlag, int nBlockUse, const char * szFileName, int nLine)  Zeile 302 + 0x1d Bytes C++
msvcr100d.dll!malloc(unsigned int nSize)  Zeile 56 + 0x15 Bytes C++
msvcr100d.dll!operator new(unsigned int size)  Zeile 59 + 0x9 Bytes C++
LogoColorDetector.exe!std::_Allocate<char>(unsigned int _Count, char * __formal)  Zeile 36 + 0xf Bytes  C++
LogoColorDetector.exe!std::allocator<char>::allocate(unsigned int _Count)  Zeile 187 + 0xb Bytes    C++
LogoColorDetector.exe!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Copy(unsigned int _Newsize, unsigned int _Oldlen)  Zeile 1933 + 0x12 Bytes C++
LogoColorDetector.exe!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Grow(unsigned int _Newsize, bool _Trim)  Zeile 1963 + 0x13 Bytes   C++
LogoColorDetector.exe!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::assign(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & _Right, unsigned int _Roff, unsigned int _Count)  Zeile 902 + 0xe Bytes C++
LogoColorDetector.exe!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> >(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & _Right)  Zeile 546 C++
LogoColorDetector.exe!compareClasses(support::ImageCollection * coll, support::ImageClass * cl1, support::ImageClass * cl2, float * mean, float * var)  Zeile 111 + 0x22 Bytes  C++

有没有人知道可能导致这种情况的原因?

感谢您的帮助。

- 编辑 -

使用Visual Leak Detector尝试了这个建议。直到上面提到的错误消息弹出并且表示内存在被释放后被修改时,它才显示任何内容。有没有办法找出哪个对象与内存地址相关联 - 内存转储似乎没有什么帮助。

为了让事情变得更加神秘,我尝试添加以下内容:

std::string tmp = imgTrain2[j]->getFilepath();
std::string t2Path = imgTrain2[j]->getFilepath();

现在第一行正确执行,第二行失败。

2 个答案:

答案 0 :(得分:9)

当运行时检测到堆损坏时,堆已经已损坏。这意味着之前的操作搞砸了它(例如:你写了一些超出数组范围的东西,你的指针已损坏等等。)。

使用可视泄漏检测器或任何可以在覆盖您不应该存储的位置的确切位置发出错误信号的工具运行程序(注意:这仍然可能不会显示代码中的错误,例如,你之前破坏了一个指针,但至少它会给你一个提示 被破坏了。)

更新:David回答的一些附录(抱歉,SO不允许长篇评论)

完成类比:你的程序中有一个错误。当执行包含错误的行时,可能会产生错误。它会覆盖堆的一部分,您可以在其中存储有关(a)已分配内存块的信息。运行时无法识别这个,该内存段属于您的进程,因此您应该能够写入它。没有失败。现在稍后(可能在应用程序的完全不同的部分)尝试分配新内存,新运算符调用heap_alloc_来获取新的内存块。 alloc的代码遍历已分配的内存块链,并在那里发现了一些垃圾。它触发了一个失败,让你知道正在发生的事情真的很糟糕。现在,您必须在代码中找到触发错误的错误。如果没有某些工具,您必须检查整个代码是否存在错误。

答案 1 :(得分:3)

当您丢弃堆时,通常会在位置和时间上将错误的来源和检测区分开来。故障,错误和失败之间存在很大差异。

通过类比的方式,考虑一下内存中的零点,但由于某种原因切换到永久停留在一个状态。这是一个错误。还没有结果。假设该位的下一个操作是命令它打开。该命令隐藏了故障;从某种意义上说,问题不存在。读者将收到一个值,正确的值。命令它为零,故障再次成为现实,但这仍然是一个问题。只有当读取器应该为零时读取器才会显示问题。此时故障已触发错误。这仍然可能不是问题;该错误可能没有影响,失败位恰好是pi的存储值的尾数的最低有效位。一些故障确实会导致问题。例如,错误的位故障可能使(确实已经造成)航天器失聪。当错误使系统以某种方式表现不佳时,错误会触发失败。

你的代码在某个地方沿着分配的内存的某些部分做了一点舞蹈。那是错。你的代码继续快乐地执行,直到它试图访问跳舞的内存:一个错误。其中一些错误可能是良性的。你的程序继续快乐,直到它到达一些关键代码,它很可能试图通过跳舞的内存访问。

我怀疑你写入imgTrain2[j]的某个地方。现在你的指针很糟糕。