CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6
  1. #1
    Join Date
    Nov 2011
    Posts
    46

    bad_aloc, can't dynamically allocate doubles

    here is my working code

    Code:
            float *songin;
            float *songout;
    	
    	float *sli;
    	float *sri;
    
    	float *slo;
    	float *sro;
    
    	int buffsz;
    	int bszl;
    
    	SNDFILE *sndin;
    	SNDFILE *sndout;
    	
    	SF_INFO songinfo;
    	SF_INFO songoutfo;
    
    	writepath=ProjectDirectoryProcessed+"\\filtered.wav";
    
    	//sndin=sf_open(in.c_str(), SFM_READ, &songinfo);
    	sndin=sf_open("C:\\MULTI bin\\take back.wav", SFM_READ, &songinfo);
    
    	buffsz=songinfo.frames*songinfo.channels*sizeof(float);
    	bszl=songinfo.frames*sizeof(float);
    
    	songin=new float[buffsz];
    	songout=new float[buffsz];
            sli=new float[bszl];
    	sri=new float[bszl];
    	slo=new float[bszl];
    	sro=new float[bszl];
    It's kind of strange to me.

    When I did this:

    Code:
    short *data;
    data =new short[songinfo.frames*songinfo.channels*sizeof(short)];
    No problems.

    When I do this,

    Code:
    float *data;
    data =new float[songinfo.frames*songinfo.channels*sizeof(float)];
    I got bad_aloc, but when I do this,

    Code:
    	float *data;
            sz=songinfo.frames*songinfo.channels*sizeof(float);
            data =new float[sz];
    no problems.

    Then, I do this,

    Code:
    	double *data;
            sz=songinfo.frames*songinfo.channels*sizeof(double);
            data =new double[sz];
    Problem.

    So I try this, just as a test

    Code:
    	double *data;
            data =new double[1000];
    bad_aloc

    So I change back to float, and now float will not allocate. So I restart my computer, and now float will allocate. Try double, bad_aloc. Restart computer, try to allocate double, bad_aloc.

    What could be causing this? I'm kind of stumped. I'm using visual studio 10 professional.
    Last edited by wl3; December 6th, 2011 at 09:02 PM.

  2. #2
    Join Date
    Apr 1999
    Posts
    27,449

    Re: bad_aloc, can't dynamically allocate doubles

    First, please realize that new[]/delete[] to create dynamic arrays is considered "old-style" and unless you're writing your own memory manager, not necessary in modern C++ programs.

    If you're coding in MFC you have CArray. If it's standard C++, you have std::vector. Both encapsulate the concept of a dynamic array, and without the dangers of not deallocating memory. They are also more efficient, especially if you're calling new[]/delete[] multiple times for the same pointer. The sooner you replace the code with either of these two classes, the better.

    Having said this, can you explain why you are using new[] as if you're calling malloc()?
    Code:
    short *data;
    data =new short[songinfo.frames*songinfo.channels*sizeof(short)];
    
    float *data;
    data =new float[songinfo.frames*songinfo.channels*sizeof(float)];
    Why are you multiplying by sizeof(short) and sizeof(float) in those two lines? It looks like you took a malloc() call, and then copy and pasted it inside operator new[].

    There is no need to be multiplying by sizeof(T). If you want x floats, then it's
    Code:
    float *p = new float[x];
    Not this:
    Code:
    float *p = new float[x * sizeof(float)];
    Also, how about giving us the numbers you're using inside of those calls to new[]? We can't see behind variable names.

    Regards,

    Paul McKenzie

  3. #3
    Join Date
    Nov 2011
    Posts
    46

    Re: bad_aloc, can't dynamically allocate doubles

    Quote Originally Posted by Paul McKenzie View Post
    First, please realize that new[]/delete[] to create dynamic arrays is considered "old-style" and unless you're writing your own memory manager, not necessary in modern C++ programs.

    If you're coding in MFC you have CArray. If it's standard C++, you have std::vector. Both encapsulate the concept of a dynamic array, and without the dangers of not deallocating memory. They are also more efficient, especially if you're calling new[]/delete[] multiple times for the same pointer. The sooner you replace the code with either of these two classes, the better.

    Having said this, can you explain why you are using new[] as if you're calling malloc()?
    Code:
    short *data;
    data =new short[songinfo.frames*songinfo.channels*sizeof(short)];
    
    float *data;
    data =new float[songinfo.frames*songinfo.channels*sizeof(float)];
    Why are you multiplying by sizeof(short) and sizeof(float) in those two lines? It looks like you took a malloc() call, and then copy and pasted it inside operator new[].

    There is no need to be multiplying by sizeof(T). If you want x floats, then it's
    Code:
    float *p = new float[x];
    Not this:
    Code:
    float *p = new float[x * sizeof(float)];
    Also, how about giving us the numbers you're using inside of those calls to new[]? We can't see behind variable names.

    Regards,

    Paul McKenzie
    The numbers inside my calls to new[], refer to a structure which is filled with audio data, when you call, sf_readf_float. The audio samples are interleaved (L,R,L,R...) Each frame, is two samples, L,R. The number of channels times the number of frames equals the amount of samples. This number for the audio file I am loading is about 20,000,000.

    I read that arrays are faster than vectors.

    I had no idea until now that it's dangerous to use dynamic memory allocation, even when used correctly.

    I'm using libsndfile to read and write audio data.

    Code:
    SNDFILE * wav;
    SNDFILE *nwav;
    
    SF_INFO wavinfo;
    SF_INFO nwavinfo;
    
    wav=sf_open( filepath, SFM_READ, &wavinfo);
    
    //then fill in the struct nwavinfo ex. nwaveinfo.channels=wavinfo.channels ...
    
    sf_readf_float( wav,  pointer to an array to fill with data, number of samples put in that array);
    
    //that fills an array with interleaved sample values.  I'm not sure I can use a vector there?
    
    nwav=sf_open( filepath, SFM_WRITE, &nwavinfo);
    
    //now you can do stuff with the data but first might want to deinterleave to process left and right separately.
    
    //dinterleave...
    
    for (n=0; n< frames ; ++n) {
    outleft[n]=intleft[n]+some math
    }
    
    //interleave..
    
    sf_writef_float(nwav, data array , number of frames);
    Regardless of my boneheaded mistake of allocating more memory than needed, the compiler stopped at allocation. So I guess the problem could be related to the amount of memory, but I don't know of any reason why this should be the case for me.

    And it is odd that allocating an array of floats works when I pass a single integer variable, but not when I use the info structure variables.

    Are there any specific rules involving allocating arrays of doubles, and floats?
    Last edited by wl3; December 7th, 2011 at 01:03 AM.

  4. #4
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: bad_aloc, can't dynamically allocate doubles

    Quote Originally Posted by wl3 View Post
    ...
    I had no idea until now that it's dangerous to use dynamic memory allocation, even when used correctly.
    It is a wrong assumption!.
    I'd say it's dangerous to use dynamic memory allocation, because is is very hard to use it correctly
    MFC CArray and std::vector classes do that dynamic memory allocation/deallocation correctly.
    Victor Nijegorodov

  5. #5
    Join Date
    Apr 1999
    Posts
    27,449

    Re: bad_aloc, can't dynamically allocate doubles

    Quote Originally Posted by wl3 View Post
    The numbers inside my calls to new[], refer to a structure which is filled with audio data, when you call, sf_readf_float.
    That's fine, but I would like to know exactly what is in the brackets in the call to new[], not a description.
    about 20,000,000.
    So does this mean:
    Code:
    float *x = new float[20000000];
    If not, please give us exact numbers you're using in the call to new[], plus the type you're calling new[] with (float, short, whatever).
    I read that arrays are faster than vectors.
    You are dealing with pointers to dynamically allocated memory, not just arrays.

    Second, using CArray or vectors for most programs, in the worst case, cause negligible speed difference when compared to new[]/delete[], and at the very best, beats new[]/delete[] by a wide margin. The only thing that CArray or vector may have an issue with is initialization when the vector/CArray is created. But as I stated, most programs initialize the allocated new[]/delete[] memory also, so that becomes a moot point.

    However, if you're repeatedly calling new[]/delete[] for the same pointer (for example, you are resizing the number of items allocated), a CArray/vector runs rings around this type of coding in terms of speed. The reason is that you're calling new[]/delete[] every time, causing the program to call the allocator and deallocator for each call. This creates a bottleneck in the program. A CArray or vector is smart enough to only call the allocator when necessary when you resize the number of items.

    But more important than that, a vector uses RAII, in other words, the vector knows how to clean up itself when it is destroyed. This means that if you have a function that throws an exception, the vector will go out of scope and clean up without you doing anything. Same thing with a function that has multiple return points -- the vector will clean up without you doing anything. With your call to new[], you have to remember to call delete[] for any and all exit points, including when an exception is thrown -- if you miss one return point, you have a memory leak. The same thing applies to CArray. It also uses RAII, so it will destroy itself when it goes out of scope.

    So if I took your function as it is, here is how it would look if it were just a little more complex:
    Code:
    songin=new float[buffsz];
    songout=new float[buffsz];
    sli=new float[bszl];
    sri=new float[bszl];
    slo=new float[bszl];
    sro=new float[bszl];
    //...
    if ( I need to return )
    {
        delete [] songin;
        delete[] songout;
        delete[] sli;
        delete[] sri;
        delete[] slo;
        delete[] sro;
        return;
    }
    //...
    else
    {
       // whatever
    }
    //..
    if ( I need to return here now )
    {
        delete [] songin;
        delete[] songout;
        delete[] sli;
        delete[] sri;
        delete[] slo;
        delete[] sro;
        return;
    }
    else
    {
       //... More code
    }
    // Now I need to make sure I do this
      delete [] songin;
        delete[] songout;
        delete[] sli;
        delete[] sri;
        delete[] slo;
        delete[] sro;
        return;
    See how tedious this is, and error-prone? Add to that, what if there is a function you're calling that throws an exception? You better code that try/catch to make sure you don't have a memory leak. Believe it or not, there is code out there that looks like this, where all of this is avoided if you use CArray or std::vector.
    I had no idea until now that it's dangerous to use dynamic memory allocation, even when used correctly.
    As VictorN stated, if you use it correctly then there is no problem. But the issue is even if you use it correctly, to get it to "work", you may have had to tie yourself up in knots with the new[] here, delete[] there, check if it's deleted already and if so call new[], or if not do this, do that, do the other. By the time you're finished, you have a working program that looks like spaghetti in terms of when you call new[] or when you call delete[].
    And it is odd that allocating an array of floats works when I pass a single integer variable, but not when I use the info structure variables.
    Like I stated, what are the real numbers in-between those brackets? How many floats? How many structs? I still don't know, and won't know until you specify how many.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; December 7th, 2011 at 06:37 AM.

  6. #6
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: bad_aloc, can't dynamically allocate doubles

    Quote Originally Posted by wl3 View Post
    I read that arrays are faster than vectors.
    In some specialized cases, it's possible to make dynamic arrays work faster than vectors. If you use vectors inefficiently, such as passing them to functions by value, it's certainly possible to make them slow.

    But used correctly, vectors will in most cases be no more than 5% slower than dynamic arrays, and often faster. And they'll save you lots of debugging time and simplify your code. In the majority of cases, that's a good trade-off.

    On those rare occasions when you need every microsecond of running time shaved off, you can do things differently. Confine that sort of coding to where you need it, though.

    NOTE: vectors do bounds-checking by default in Visual Studio, even under Release mode. This is great for debugging but can be slow. You need to set a preprocessor symbol to disable it before doing any speed tests.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured