-3

I have to do some kind of project and I'm stuck. I'm getting an bad_alloc error. I checked code a lot of times, tried to google some solutions, but still nothing, that's why I'm writing here.The thing is the program runs normally, but at the task manager he memory usage raises to 2GB(that's the limit as I know) and then it crashes. The program needs to check time of allocating space and copying variables. Here's part of the code:

class Table
{
    int *tablica;
    int size;

public:
Table()
    {
        tablica = NULL;
        size = 0;
    }

~Table()
    {
        delete tablica;
        size = 0;
    }

int *push_back(int val)
    {
        int *temp = new int[size];
        if(size % 10 == 0)
        {
            for(int i = 0; i < size; i++)
                temp[i] = tablica[i];
            tablica = new int[size + 10];
            for(int i = 0; i < size; i++)
                tablica[i] = temp[i];
        }
        tablica[size] = val;
        size++;
        delete []temp;
        return tablica;
    }

void test()
    {
            LONGLONG measure[100][6];
        LARGE_INTEGER performanceCountStart, performanceCountEnd;
        int cpy_tab [20000];

        for(int j = 0; j < 100; j++)
        {   
            for(int i = 0; i < 20000; i++)
                cpy_tab[i] = rand() % 10000 - 10000;

            performanceCountStart = startTimer(); 
            for(int i = 0; i < 500; i++)
                {
                    push_back(cpy_tab[i]);
                }
            performanceCountEnd = endTimer();
    measure[j][0] = performanceCountEnd.QuadPart - performanceCountStart.QuadPart;
            cout<<j<<"."<<measure[j][0]<<endl;

            delete []tablica;
            size = 0;

            performanceCountStart = startTimer(); 
            for(int i = 0; i < 2000; i++)
            {
                push_back(cpy_tab[i]);
            }
            performanceCountEnd = endTimer();
    measure[j][1] = performanceCountEnd.QuadPart - performanceCountStart.QuadPart;
            cout<<j<<"."<<measure[j][1]<<endl;

            delete []tablica;
            size = 0;


            performanceCountStart = startTimer(); 
            for(int i = 0; i < 4000; i++)
            {
                push_back(cpy_tab[i]);
            }
            performanceCountEnd = endTimer();
    measure[j][2] = performanceCountEnd.QuadPart - performanceCountStart.QuadPart;
            cout<<j<<"."<<measure[j][2]<<endl;

            delete []tablica;
            size = 0;


            performanceCountStart = startTimer(); 
            for(int i = 0; i < 8000; i++)
            {
                push_back(cpy_tab[i]);
            }
            performanceCountEnd = endTimer();
    measure[j][3] = performanceCountEnd.QuadPart - performanceCountStart.QuadPart;
            cout<<j<<"."<<measure[j][3]<<endl;

            delete []tablica;
            size = 0;


            performanceCountStart = startTimer(); 
            for(int i = 0; i < 14000; i++)
            {
                push_back(cpy_tab[i]);
            }
            performanceCountEnd = endTimer();
    measure[j][4] = performanceCountEnd.QuadPart - performanceCountStart.QuadPart;
            cout<<j<<"."<<measure[j][4]<<endl;

            delete []tablica;
            size = 0;

            performanceCountStart = startTimer(); 
            for(int i = 0; i < 20000; i++)
            {
                push_back(cpy_tab[i]);
            }
            performanceCountEnd = endTimer();
    measure[j][5] = performanceCountEnd.QuadPart - performanceCountStart.QuadPart;
            cout<<j<<"."<<measure[j][5]<<endl;

            delete []tablica;
            size = 0;
        }
    }

Any ideas of resolving this problem would be really worthy to me!

Mohit Jain
  • 30,259
  • 8
  • 73
  • 100
Robs
  • 153
  • 2
  • 10
  • 1
    can't you provide us with a shorter example? and what is wrong with nested for loops? is it really necessary to have so much code copied & pasted again? – xmoex Apr 07 '14 at 07:18
  • 1
    If you suspect a memory leak, run it through `valgrind` and see what comes out the other end. Also, please try to reduce the size of your example to the minimum compilable example which reproduces the problem. You will often find that in trying to isolate this minimum example, you have already discovered the answer. – merlin2011 Apr 07 '14 at 07:20
  • Please debug first and narrow your question. Also using a memory leak detector like valgrind would be a good idea. Most probably you are leaking somewhere, and the consumed memory unexpectedly accumulates. – πάντα ῥεῖ Apr 07 '14 at 07:20
  • Correctly indenting the code is a first step. The second one is using `std::vector` instead of `new[]` and `delete[]`. –  Apr 07 '14 at 07:21
  • Ok, I'll try to use valgrind or it's substitute, cause I'm using Windows not Linux and then specify what's going on. I unfortunately cannot use any vector-like class. – Robs Apr 07 '14 at 07:31

3 Answers3

2

You are definitely leaking, and probably fragmenting the memory when you do this:

    int *temp = new int[size];
    if(size % 10 == 0)
    {
        for(int i = 0; i < size; i++)
            temp[i] = tablica[i];
        // Should free tablica here 
        tablica = new int[size + 10];
        for(int i = 0; i < size; i++)
            tablica[i] = temp[i];
    }

First, you allocate a temp (even if you don't need to) which is size elements, then you allocate a size+10 elements array, which is not freed.

I would suggest that you use a second variable to record the capacity, and double the capacity each time you're at the capacity. That way, you don't need 2000 allocations to grow the array to 20000 elements, but 15 re-allocations (and copies).

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • I don't think there's a leak - the expanded array (with 10 additional elements) is tracked in the `tablica` pointer, which is deleted at various points in `test()` and (improperly) deleted in the dtor. However, I would say that the code managing the `tablica` pointer is rather messy. – Michael Burr Apr 07 '14 at 07:38
  • 2
    It's deleted after the loop, but not IN the loop. So in a loop of 1000 elements, 100 allocations are made, and only one delete after the loop. – Mats Petersson Apr 07 '14 at 07:50
  • You're right - I see what I missed now. – Michael Burr Apr 07 '14 at 07:53
  • The rest of the code isn't exactly fantastic either, but the leak here is what kills the memory. The fragmentation isn't helping either. – Mats Petersson Apr 07 '14 at 07:55
  • Thanks a lot Mats Petersson. It just worked. Now I understand what to do for the future operations like this. And sorry for little bit messy code. I still need to learn a lot :) – Robs Apr 07 '14 at 07:59
  • You should mark this as the correct answer, so that others that look at the question will know that it's been answered. – Mats Petersson Apr 07 '14 at 08:25
1

You don't show exactly how you're using the Table class, but you're probably corrupting the heap.

The test() function repeatedly pushes data onto tablica then does a delete [] tablica before doing another round of pushes.

However, when the test() function deletes tablica the last time, it doesn't set the poitner to NULL, and the Table desctuctor looks like:

~Table()
{
    delete tablica;
    size = 0;
}

So it would go ahead and delete that pointer again causing the heap to get corrupted. Note that the delete operation in ~Table() should be a delete [] tablica;.

Also, note that having the tablica pointer managed across the push_back(), test() and dtor functions makes for a messy situation.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
1

Because you are leaking tablica memory. Before

tablica = new int[size + 10];

Add a line

delete []temp;

And everything would be fine.

More over in every call of push_back you are unnecessarily allocating memory in temp and deleting it. Instead allocate the memory and free inside if condition.

Mohit Jain
  • 30,259
  • 8
  • 73
  • 100