`std::vector` throws a "bad allocation" exception when resized

uahakan picture uahakan · Feb 19, 2014 · Viewed 7.3k times · Source

I have the following code in a C++ dll, which I invoke through JNI:

std::vector<double> myVector;
myVector.resize(10000000, 0);

I get a "bad allocation" exception, even though the maximum size for the vector is supposedly larger than 10000000.

What tool should I be using to track memory allocation, in order to locate any memory leaks?

If there are really no memory leaks, how can I reduce the footprint of the vector in order to ensure I have enough space?

Answer

Brandon picture Brandon · Feb 19, 2014

I know this is probably the worst solution to find out your allocation size. So here goes:

main.cpp:

#include "jni.h"
#include <vector>
#include <iostream>

#if (_MSC_VER == 1800) || (__cplusplus >= 201103L)
    #include <thread>
    #include <chrono>
#elif _MSC_VER
    #include <windows.h>
#else
    #include <unistd.h>
#endif


extern "C" JNIEXPORT void Java_test_Test_Alloc(JNIEnv* env, jobject obj, jint max_size, jint increment_size)
{
    std::vector<double> vec;
    size_t isize = max_size / 4;
    size_t oldsize = isize;

    while(isize <= max_size)
    {
        try
        {
            vec.resize(isize, 0);
            oldsize = isize;
            isize += increment_size;
            std::cout<<"Allocated: "<<vec.size() * sizeof(double)<<" bytes.\n";
        }
        catch (std::bad_alloc &e)
        {
            std::cout<<"Failed to allocate: "<<isize * sizeof(double)<<" bytes.\n";
            std::cout<<"Approx. max size: "<<oldsize * sizeof(double)<<" bytes.\n";
            std::cout<<"Exception: "<<e.what()<< "\n";
            std::cout<<"Vector.Max_Size(): "<<vec.max_size()<< "\n";
            break;
        }

        #if (_MSC_VER == 1800) || (__cplusplus >= 201103L)
            std::this_thread::sleep_for(std::chrono::seconds(1));
        #elif _MSC_VER
            Sleep(1);
        #else
            sleep(1);
        #endif
    }
}

#if defined _WIN32 || defined _WIN64
#include <windows.h>

extern "C" __declspec(dllexport) bool __stdcall DllMain(HINSTANCE hinstDLL, unsigned fdwReason, void* lpvReserved)
{
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            break;

        case DLL_PROCESS_DETACH:
            break;
    }
    return true;
}
#endif

And on the Java side (Test.java):

package test;

public class Test {

    static {
        System.loadLibrary("JNITest");
    }

    public static native void Alloc(int max_size, int increment_size);

    public static void main(String[] args) {
        Alloc(100000000, 50000);
    }

}

For me, it prints:

Allocated: 200000000 bytes.
Allocated: 200400000 bytes.
Allocated: 200800000 bytes.
.
.
.
Allocated: 399600000 bytes.
Allocated: 400000000 bytes.
Failed to allocate: 400400000 bytes.
Approx. max size: 400000000 bytes.
Exception: std::bad_alloc
Vector.Max_Size(): 536870911

Like I said.. it is a bad way to "guess" at how much you can allocate but in this case, no one else has posted anything so I'm going to leave this here and you can use it if you wish..