bad_alloc with no memory leak?

Pages: 12
Aug 19, 2011 at 9:28am
Hello guys, :)

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 :)
Aug 19, 2011 at 9:31am
http://cplusplus.com/reference/std/new/bad_alloc/

states that that exception is thrown when you cannot allocate enough memory, so it sounds like you are running out of memory somewhere in there.
Aug 19, 2011 at 9:32am
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?
Last edited on Aug 19, 2011 at 9:33am
Aug 19, 2011 at 9:49am
Thank you for your answers :)

@firedraco: How could I run out of memory when there are no memory leaks? I analysed 30 GB of the file and then got the error!

@Jonc: I don't think it's a negative number. I checked all the resize commands, they all have numbers that can't be negative!

@Athar: If there are no memory leaks, I don't think it's a problem to allocate and de-allocate this amount of memory. Right?

Here's the main() of my code. Assuming what Athar has said is right, the error must be here!

mmap_cpp is a wrapper class for file-memory mapping

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
int main(int argc, char** argv)
{
    long int threads = 1;
    double samplingRate = pow(10,-6);
    vector< vector<double> > readData;
    vector<double> timeVec;
    string filename = "/xdata/common/labdata/2011/07-27-PulsesAnalysis/Data/Signal_Amp_002521.75000_sr_1e-06_pr_0_lphp_.bin";
    size_t cropFront = 1000;
    size_t cropEnd = 300;
    size_t pulsesBuffer = 1000;
    size_t periodLengthInPoints = 20001;
    long long int batchCounter = 0;
    fstream omegaOutput("/xdata/common/labdata/2011/07-27-PulsesAnalysis/Data/OmegaOutputFilteredlphp.bin", ios::out | ios::binary);
    double freq;
    omegaOutput.clear();
    mmap_cpp<double> signalRead;
    signalRead.openfile(filename,10,0,1,0);
    cout << signalRead.getSizeByElements() / periodLengthInPoints << endl;
    if (threads = 1)
    {
        for (size_t i = 0; i < signalRead.getSizeByElements() / periodLengthInPoints; i++)
        {
            cout << i << endl;
            batchCounter = floor(i / pulsesBuffer);
            cout << "Batch number: " << batchCounter << endl;
            if (i >= batchCounter * pulsesBuffer)
            {
                ReadFIDs<double>(signalRead, filename, readData, batchCounter*pulsesBuffer, periodLengthInPoints, pulsesBuffer, cropFront, cropEnd);
                omegaOutput.flush();
            }
            freq = GetFrequency(readData[i - batchCounter * pulsesBuffer], 5, samplingRate);
            cout << freq << endl;
            omegaOutput.write((char*) &freq, sizeof (freq));
        }
    }
    omegaOutput.close();
    return 0;
}


Any ideas? I can't put the rest of the code. It's HUGE!!!!!

Any help is highly appreciated :)
Last edited on Aug 19, 2011 at 9:49am
Aug 19, 2011 at 10:25am
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.
Aug 19, 2011 at 10:36am
You seem to be allocating around 2gb (give or take some) which could be more than the system will give to a single process.
Aug 20, 2011 at 10:17am
Thank you for your replies! :)

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

I'm using Netbeans debugger and ddd.

Any efforts are highly appreciated!!!

Aug 20, 2011 at 3:37pm
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.
Aug 21, 2011 at 4:38am
Thank you for your reply! :)

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.

:)
Aug 21, 2011 at 12:23pm
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???
Aug 21, 2011 at 1:43pm
closed account (DSLq5Di1)
If you are not able to break on the exception and check your call stack.. you may have better luck using another IDE, give VC++ Express [1] a whirl.

You might also try catching the bad_alloc exception or set the new handler [2], and output your own debugging information.

[1] http://www.microsoft.com/visualstudio/en-us/products/2010-editions/visual-cpp-express
[2] http://www.cplusplus.com/reference/std/new/set_new_handler/
Aug 21, 2011 at 2:44pm
Thank you for your answer :)

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?
Aug 21, 2011 at 2:54pm
malloc has some debug functions -- mallocstats or mallinfo IIRC. Try calling them to what the state of the heap is.

Aug 21, 2011 at 3:12pm
As you are using linux you may benefit from examining core dump files:

http://en.linuxreviews.org/HOWTO_enable_core-dumps

Aug 22, 2011 at 5:23am
Thank you.

I'll try these things and get back to you :)
Aug 22, 2011 at 11:30am
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?
Last edited on Aug 22, 2011 at 11:33am
Aug 22, 2011 at 12:49pm
closed account (1vRz3TCk)
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?
Aug 22, 2011 at 1:11pm
Thanks again for your replies :)

@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:

1
2
template <typename T>
void ReadFIDs(mmap_cpp<T>& fileMap, string& filename, deque< vector<T> >& dest, const size_t indexOfPulse, const size_t FIDLengthInPoints, const size_t FIDsToRead, const size_t cropFront = 0, const size_t cropEnd = 0)


@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.
Aug 22, 2011 at 3:03pm
Hmm, could you check if dmesg tells something (or the files in /var/log), in case the kernel gives some details about the allocation error?
Aug 22, 2011 at 3:37pm
Thank for your concern.

I got dmesg output saved to a file. Please find it under this link:

http://www.megaupload.com/?d=WZZEGKY0

I couldn't understand a word from it. Does it tell you anything? the program is called blochsim.
Pages: 12