So, I need some help. I am working on a project in C++. However, I think I have somehow managed to corrupt my heap. This is based on the fact that I added an std::stri
These are relatively cheap mechanisms for possibly solving the problem:
new[]
and delete[]
, but you're already doing that.assert()
ing enough in your code. How do I know that without having seen it? Like flossing, no-one assert()
s enough in their code. Add in a validation function for your objects and call that on method start and method end.auto_ptr
! That thing is... surprising; its semantics are very odd. Instead, choose one of the Boost smart pointers, or something out of the Loki library.We once had a bug which eluded all of the regular techniques, valgrind, purify etc. The crash only ever happened on machines with lots of memory and only on large input data sets.
Eventually we tracked it down using debugger watch points. I'll try to describe the procedure here:
1) Find the cause of the failure. It looks from your example code, that the memory for "exampleString" is being corrupted, and so cannot be written to. Let's continue with this assumption.
2) Set a breakpoint at the last known location that "exampleString" is used or modified without any problem.
3) Add a watch point to the data member of 'exampleString'. With my version of g++, the string is stored in _M_dataplus._M_p
. We want to know when this data member changes. The GDB technique for this is:
(gdb) p &exampleString._M_dataplus._M_p
$3 = (char **) 0xbfccc2d8
(gdb) watch *$3
Hardware watchpoint 1: *$3
I'm obviously using linux with g++ and gdb here, but I believe that memory watch points are available with most debuggers.
4) Continue until the watch point is triggered:
Continuing.
Hardware watchpoint 2: *$3
Old value = 0xb7ec2604 ""
New value = 0x804a014 ""
0xb7e70a1c in std::string::_M_mutate () from /usr/lib/libstdc++.so.6
(gdb) where
The gdb where
command will give a back trace showing what resulted in the modification. This is either a perfectly legal modification, in which case just continue - or if you're lucky it will be the modification due to the memory corruption. In the latter case, you should now be able to review the code that is really causing the problem and hopefully fix it.
The cause of our bug was an array access with a negative index. The index was the result of a cast of a pointer to an 'int' modulos the size of the array. The bug was missed by valgrind et al. as the memory addresses allocated when running under those tools was never "> MAX_INT
" and so never resulted in a negative index.
Your code as I can see has no errors. As has been said more context is needed.
If you haven't already tried, install gdb (the gcc debugger) and compile the program with -g. This will compile in debugging symbols which gdb can use. Once you have gdb installed run it with the program (gdb <your_program>). This is a useful cheatsheat for using gdb.
Set a breakpoint for the function that is producing the bug, and see what the value of exampleString is. Also do the same for whatever parameter you are passing to exampleString. This should at least tell you if the std::strings are valid.
I found the answer from this article to be a good guide about pointers.
One of the debugging techniques that I use frequently (except in cases of the most extreme weirdness) is to divide and conquer. If your program currently fails with some specific error, then divide it in half in some way and see if it still has the same error. Obviously the trick is to decide where to divide your program!
Your example as given doesn't show enough context to determine where the error might be. If anybody else were to try your example, it would work fine. So, in your program, try removing as much of the extra stuff you didn't show us and see if it works then. If so, then add the other code back in a bit at a time until it starts failing. Then, the thing you just added is probably the problem.
Note that if your program is multithreaded, then you probably have larger problems. If not, then you should be able to narrow it down in this way. Good luck!
Some places to start:
If you're on windows, and using visual C++6 (I hope to god nobody still uses it these days) it's implentation of std::string is not threadsafe, and can lead to this kind of thing.
Here's an article I found which explains a lot of the common causes of memory leaks and corruption.
At my previous workplace we used Compuware Boundschecker to help with this. It's commercial and very expensive, so may not be an option.
Here's a couple of free libraries which may be of some use
http://www.codeguru.com/cpp/misc/misc/memory/article.php/c3745/
http://www.codeproject.com/KB/cpp/MemLeakDetect.aspx
Hope that helps. Memory corruption is a sucky place to be in!
Other than tools like Boundschecker or Purify, your best bet at solving problems like this is to just get really good at reading code and become familiar with the code that you're working on.
Memory corruption is one of the most difficult things to troubleshoot and usually these types of problems are solved by spending hours/days in a debugger and noticing something like "hey, pointer X is being used after it was deleted!".
If it helps any, it's something you get better at as you gain experience.
Your memory allocation for the array looks correct, but make sure you check all the places where you access the array too.