1

我对 C++ 内存管理比较陌生,而且我遇到了这个奇怪的堆损坏错误(加上之前 Visual Studio 中的一个自动断点)。这是有问题的代码:

z_world::z_world(char* name)
{
    unsigned int i, skip;
    char tmp;

    //Load data from file
    std::string* data = loadString(name);

    //Base case if there is no world data
    tiles = NULL;

    w = 0;
    h = 0;

    if(data->length() > 0) {
        //Set up the 'tiles' array
        for(i = 0; i < data->length(); i++) {
            if(data->at(i) == '\n')
                h++;
            if(h == 0)
                w++;
        }
        tiles = new int[data->length()-h];

        //Load Data
        skip = 0;
        for(i = 0; i < data->length(); i++) {
            if(data->at(i) == '\n') {
                skip++;
                printf("\n");
                continue;
            }
            tmp = data->at(i);
            tiles[i+skip] = atoi(&tmp);
            printf("%i ",tiles[i+skip]);
        }
    }
    delete data;
}

这是我在字符串中加载的位置:

std::string* loadString(char* name)
{
    ifstream in(name);
    std::string* input = new string();

    while(in) {
        std::string line;
        getline(in,line);
        input->append(line);
        input->append("\n");
    }

    in.close();

    return input;
}

我在“删除数据”中得到了断点和错误;这让我认为“数据”在此之前的某个地方被删除了,但我找不到它会在哪里。作为参考,此方法是创建一个包含游戏世界数据的对象,该对象以虚拟 2D 整数数组的形式(用于图块的 ID)。

4

5 回答 5

7

你的问题可能在这里:

tiles[i+skip] = atoi(&tmp);

问题1:
应该是-skip

tiles[i - skip] =

问题 2:
命令atoi()使用不正确(tmp 不包含字符串)。但我也不认为atoi()是合适的方法。我认为您正在寻找的是简单的任务。从 char 到 int 的转换是自动的:

 tiles[i - skip] = tmp;

问题 3:
您没有正确使用对象。在这种情况下,没有必要生成动态对象和动态内存管理造成混乱。只创建自动对象并正常传递它们会更简单:

std::string* loadString(char* name)
      //   ^  Don't do this.



std::string loadString(std::string const& name)
//  ^^^^^^^  return a string by value.
//           The compiler will handle memory management very well.

一般来说,您不应该传递指针。在您确实需要指针的少数情况下,它们应该保存在智能指针对象或容器(用于多个对象)中,以便正确控制它们的寿命。

于 2012-08-12T19:56:08.363 回答
1

atoi(&tmp); atoi 需要一个指向空终止字符串的指针 - 而不是指向 char 的指针

于 2012-08-12T19:55:14.653 回答
0

可能是该函数的变量输入是本地的。因此,从这里返回后,内存被释放。因此,稍后在此字符串上调用 delete 会尝试释放已释放的内存。

于 2012-08-12T20:20:03.287 回答
0

无需在您显示的代码中动态分配字符串。loadString将函数更改为

std::string loadString(char* name)
{
    ifstream in(name);
    std::string input;

    // ...

    return input;
}

在调用者

std::string data = loadString( name );

现在完成后就不需要delete字符串了。

代替

int *tiles = NULL;
tiles = new int[data->length()-h];

利用

std::vector<int> tiles;
tiles.resize(data.length() - h);

此外,如果您确实需要动态分配对象,您应该使用智能指针 ( std::unique_ptrand std::shared_ptr) 而不是原始指针。

于 2012-08-12T19:54:16.037 回答
0

有一个错误

tiles[i+skip] = atoi(&tmp);

例如,对于一个字符串

Hello\n
World\n

并且对于点的循环迭代i == 10skip已经是 1(因为我们之前遇到过第一个\n)并且您正在写入tiles[10 + 1],但tiles仅被分配为具有 10 个元素的数组。

于 2012-08-12T19:57:51.627 回答