I'm facing a very weird problem. I got in my program an std::bad_alloc exception in a program that has no leaks at all. I don't have much experience in memory leak problems, since I'm very organised in my programming. I use templatised classes and STL containers to avoid memory leaks.
The program's purpose is basically signal analysis. A signal is stored in a 78.5 GB file. The program reads almost 2 Million doubles from that file, and analyses them, then outputs the result in a file-stream.
To be on the safe side, I used valgrind to ensure that the program doesn't leak at all (my first use ever of valgrind). I ran the program with a small part of the file (because the full analysis of the file takes 24 hours). The report of valgrind ended with this message:
----------------
HEAP SUMMARY:
in use at exit: 0 bytes in 0 blocks
total heap usage: 24,727 allocs, 24,727 frees, 1,894,576,355 bytes allocated.
All heap blocks were freed -- no leaks are possible
-----------------------
What's so strange about this, is that the error happened after analysing almost 30 GB of the file overnight!!
How could this ever be possible? if the program is running uniformly along all this size of the file, and there are no memory leaks, how could this happen? I mean, how could the program be able to re-allocate all this space, and then suddenly simply fail and throw an exception?
Are there any other causes I'm not aware of?
Thanks in advance, any efforts are highly appreciated :)
Don't know that much about memory leaks either, but I'm pretty sure you get a bad alloc if you're trying to allocate a negative number. Perhaps you have an overflow?
The reason why you don't have enough memory isn't necessarily a memory leak. You might free that memory too late. You need to check the time when you allocate und when you free the memory.
Due to paging you can allocate more memory then physically available. It slows down the whole computer though.
The program requires almost 2 hour to reach that state of std::bad_alloc. Along this time memory usage doesn't go over 0.2%!!!!!!!!! I reduced the amount of read data to 10 MB per cycle, and still I'm getting the same error :(, Any explanation?
Debugging this is the hardest thing I've ever done! the debugger isn't catching the error for some reason I can't understand!!!!!! it just gives an error and doesn't show me the line where the error is happening! what can I do???
std::vector<>, when it needs to grow, doubles its size. Consider the implications of this:
It starts at size 1, then doubles to size 2. It frees the first buffer which had room for 1 element, then had to allocate a completely new buffer for size 2. In a perfect world, the size 2 buffer is immediately adjacent to the size 1 buffer. When it doubles again to size 4, it can't reuse either of the previous buffers because in a perfect world they are big enough for only 3 elements. When it doubles again to size 8, the previous buffers, if contiguous, have room for only 7 elements.
The end result is that the vector's internal buffer keeps moving "up" in memory as the vector grows, and can never move "back". This can mean std::vector<> can throw a std::bad_alloc long before you run out of memory.
The way to get around this is either to prefer std::deque to std::vector when the elements don't have to be in contiguous memory, or use std::vector<>::reserve to reserve the number of elements you'll need ahead of time to prevent the constant reallocation.
I've begun to use deque earlier, but in the form deque<vector<double> >. I'll switch to deques for all containers that have to do with processing. I'll update you with how it goes.
Oh my god! I changed everything to deques and yet I get the same std:bad_alloc at the same point (same batch number) where it happened with vectors! and the program went 5 times slower :(
Guys I'm even unable to debug the error! I can't follow it and debuggers aren't catching the error! could you guys tell me what would you do next???
Unfortunately, my code involves file-memory mapping which is done for linux. I can't switch to windows stuff!!!
What kind of information would you output in such a situation? The problem is very weird for me I can't know where to start! I mean memory is there, memory is clean, and yet it gives a bad_alloc! how would you start with such a problem?
Could you try passing signalRead and readData by reference to ReadFIDs()? If passed by value, they will be copied, so their size will need to be allocated a second time.
EDIT : ah, readData must be passed by reference already if ReadFIDs is what is filling it
If you know that your error is an exeption, can't you put a try..catch block, and reduce it's scope gradually to see where the problem occurs?
yet I get the same std:bad_alloc at the same point (same batch number)
Possibly a silly but have you checked the input data? You do say it is at the same point, could there be an errant value that is causing the program to crash? Or could you set a breakpoint to trip at this batch number so you can examine what is going on?
@bartoli: The bad_alloc is happening at a very simple vector< vector<double> > allocation statement. That's why it's been driving me crazy. I mean the memory is empty and such a trivial allocation problem is happening.
btw, the way the function is written is as follows. I already pass almost everything by reference:
@CodeMonkey: The input data was used before with some other tools. Sorry to disappoint.
-------------------
Anyway, it's a miraculous and non-understandable thing that the program works by just reducing the buffer to "1"!!!!!!!!!!!!! i.e., mapping only 20001 doubles into memory rather than 200010... which doesn't make sense and which I can't understand!
and now the program works to the end, but I can't understand how it works and why it drew the problem in the first place!!!
Thank you for all your efforts. I still appreciate any suggestions on this weird problem.