正确删除char **?

时间:2009-10-12 18:33:06

标签: c++ memory-management

我使用以下方法创建了一个二维c字符串数组:

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

然后我使用:

初始化每一行
my_array[i] = new char[M]; // where M is a varying number. assign values to my_array[i] later

所以我几乎有一个锯齿状的2D阵列。

我想继续并删除这样的全部内容:

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

然后是:

delete [] my_array;

for循环给了我HEAP CORRUPTION ERROR - 为什么?

**************更新 - 完整代码*********************

#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;
}

如果您没有安装boost:将BOOST_AUTO_TEST_CASE转换为main()和voil'a。

上述内容的作用:将矢量转换为char **

3 个答案:

答案 0 :(得分:6)

您的代码似乎是正确的。您的堆损坏可能是由其他一些代码引起的,只有在运行此解除分配代码时才会检测到。

您可以通过单独运行上面的代码来检查这一点,而不需要任何其他代码。您应该能够验证没有堆损坏。

根据您的开发环境,调出编译器中的所有内存分配检查旋钮,或使用valgrind等工具。

答案 1 :(得分:3)

在数组初始化代码中,为每个'tokens [i]'元素分配'tokens [i] .size()'字符,然后将元素从0初始化为'tokens [i] .size()'。这显然是内存溢出。如果你想拥有从0到'tokens [i] .size()'的元素,你需要分配一个大小为'tokens [i] .size()+ 1'的数组。

答案 2 :(得分:2)

您的说明听起来不错,但您发布的代码不完整。特别是如果你只打电话

my_array[i] = new char[M];

对于数组的某些元素(并非所有N),那么你将在其他元素中有垃圾,这将导致在你看到的删除循环中检测到堆损坏。