简体   繁体   中英

Memory allocation / Heap corruption in std::string constructor

I have some trouble with memory allocation again and I can't figure out why.

When I run the program in debug mode I recieve the following error message (I tried to translate it as accurately as possible):

Windows has triggered a breakpoint in LogoColorDetector.exe. This can be caused by heap corruption which indicates a problem in LogoColorDetector.exe or one of its loaded DLLs[...]

When I debug the program I found that the problem seems to occur in the following line:

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

The getFilepath()-Function is implemented as follows:

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

I have already checked if the Image-object at imgTrain[j] has a correct _filePath string. So I assume the problem is somewhere else. The funny thing is, that the function that contains the problematic line seems to work. It's only the second time I call the function where it fails which would indicate that the problem is not in the function itself. I don't allocate any memory nor do i delete anything in the function except what is maybe done indirectly through std::string

In case it is a help for anyone, here the stack trace:

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++

Does anyone have an idea on what could cause this?

Thanks for your help.

-- edit --

Tried the suggestion with Visual Leak Detector. It doesn't show anything until the moment the above mentioned error message pops up and says that memory was modified after it has been freed. Is there a way to find out what object was associated with the memory address - the memory dump doesn't seem to be very helpful.

To make things more myterious I tried adding the following line:

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

Now the first line is executed correctly and the second line fails.

When the runtime detects a heap corruption the heap is already corrupted. It means that a previous operation messed it up (eg: you wrote something beyond the range of an array, you have corrupted pointers, etc..).

Run you program with visual leak detector or any tool that can signal the error at the exact point where you overwrite a memory location you shouldn't be (Note: this still might not show the error in your code, for example if you corrupted a pointer earlier, but at least it will give you a hint what is corrupted).

Update : some addendum to David's answer (sorry, SO doesn't allow long comments)

To finish the analogy: there is a bug in your program. When the line containing the bug is executed, it might create an error. It overwrites a part of the heap where you store information about (an) allocated memory chunk(s). The runtime doesn't recognise this, that memory segment belongs to your process, so you should be able to write to it. No failure. Now later (maybe in a completely different part of your app) you try to allocate new memory, the new operator calls heap_alloc_ to get a new memory chunk. The code for alloc walks through the the chain of allocated memory chunks and founds some garbage there. It triggers a failure to let you know that something really bad is going on. Now you have to find the bug in your code that triggered the error. Without some tool you have to check your whole code hunting for a bug.

When you trash the heap it is common for the source and detection of the error to be widely separated in location and in time. There is a big difference between faults, errors, and failures.

By way of analogy, think of a bit in memory that was at zero but for some reason switches to the permanently stuck at one state. This is a fault. No consequences yet. Suppose the next operation on the bit is to command it on. The command has hidden the fault; in a sense the problem doesn't exist. Readers will receive a one value, the correct value. Command it to zero and the fault is real again, but this remains a non-problem. The problem doesn't manifest until a reader reads a one when the bit should have been zero. At this point the fault has triggered an error. This still might not be a problem; the error may have no impact the failed bit happened to be the least significant bit of the mantissa of the stored value of pi. Some bit failures do cause problems. The wrong bit failure might make (indeed, has made) a spacecraft go deaf, for example. An error triggers a failure when the error makes a system behave badly in some way.

Your code somewhere along the line did a little dance on some part of allocated memory. That was the fault. Your code went on merrily executing until it tried to access the danced-upon memory: An error. Some of these errors were probably benign. Your program continued merrily along until it got to some critical code where it most likely tried to access through the danced-upon memory.

I suspect that somewhere along the line you wrote into imgTrain2[j] . Now you have a bad pointer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM