views:

163

answers:

3

I've created a 2d array of c-strings using :

char ** my_array = new char*[N];

and then I initialized each row using :

my_array[i] = new char[M]; // where M is a varying number. assign values to my_array[i] later

So I pretty much got a jagged 2d array.

I wanted to proceed and delete the whole thing like this :

for(int i = 0; i < N; i++)
{ delete [] my_array[i]; }

followed by a :

delete [] my_array;

the for loop gave me HEAP CORRUPTION ERROR - why?

********** UPDATE - full code *****************

#define BOOST_TEST_MODULE ARGS
#define BOOST_LIB_DIAGNOSTIC

#include <string>
#include <vector>
#include <iostream>
#include <boost/test/unit_test.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/assign.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/assign/std/vector.hpp>

using namespace std;
using namespace boost;
using namespace boost::assign;

typedef vector<string> string_array;

BOOST_AUTO_TEST_CASE(test1)
{
    string_array args = list_of
     ("aaa")("bbbb")("ccccccc")("dd")("eeeeeeeee")("ff")("g")("hhh");

    string_array tokens;

    string arg = "";
    for(int i = 0; i < (int)args.size(); i++)
    {
        arg += args[i];
        if(i != (int)args.size() - 1)
                arg += " ";
    }

    split(tokens, arg, is_any_of(" "));

    char ** new_args = NULL;
    new_args = new char*[(int)tokens.size() + 1];
    new_args[(int)tokens.size()] = 0;
    for(int i = 0; i < (int)tokens.size(); i++)
    { 
        new_args[i] = new char[(int)tokens[i].size()];
        for(int j = 0; j <= (int)tokens[i].size(); j++)
        {
      if(j == (int)tokens[i].size())
       new_args[i][j] = '\0';
      else
                new_args[i][j] = tokens[i][j];

        }
    }

    for(int i = 0; i < (int)tokens.size(); i++)
    { 
     std::cout << new_args[i] << std::endl; 
    }

    for(int i = (int)tokens.size() - 1; i >= 0; i--)
     delete new_args[i]; 

    delete [] new_args;
}

If you don't have boost installed : convert the BOOST_AUTO_TEST_CASE to main() and voil'a.

What the above thing does : converts a vector into char **

+6  A: 

Your code appears to be correct. Chances are that your heap corruption is caused by some other code, and is only detected when this deallocation code is run.

You can check this by running the above code in isolation, without any other code around it. You should be able to verify that there is no heap corruption from this.

Depending on your development environment, turn up all the memory allocation checking knobs in your compiler, or use a tool such as valgrind.

Greg Hewgill
already have, I'm using boost/test/unit_test.hpp framework, it's got a pretty nice mem-leak tracing build in the unit tests.If I skip the looped delete [] I get a mem leak as individual rows aren't de-allocated. if I add it - WHAM - heap corruption error
Maciek
Sounds like you're on the right path with instrumentation. However, memory leak detection won't detect writing past the end of an allocated array. For example, since you're allocationg `my_array` with N elements, ensure that you're not storing anything in `my_array[N]`. If you are, that would be past the end of the allocated array.
Greg Hewgill
+2  A: 

Your description sounds correct, but the code you've posted is incomplete. In particular if you only call

my_array[i] = new char[M];

for some elements of the array (not all N), then you'll have garbage in the other elements, which will cause the heap corruption detected in the delete loop you see.

Chris Dodd
+2  A: 

In your array initialization code you allocate 'tokens[i].size()' characters for each 'tokens[i]' element, and then you initialize elements from 0 to 'tokens[i].size()'. This is obvious memory overrun. If you want to have elements from 0 to 'tokens[i].size()', you need to allocate an array of size 'tokens[i].size() + 1'.

AndreyT
oh god, I just noticed that. THANKS A TON.
Maciek