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

「deletedata;」内にブレークポイントとエラーが発生し、「data」がその前のどこかで削除されたように思われますが、どこで削除されるかわかりません。参考までに、このメソッドは、仮想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は、文字へのポインタではなく、nullで終了する文字列へのポインタを想定しています。

于 2012-08-12T19:55:14.653 に答える
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_ptrおよび)を使用する必要があります。std::shared_ptr

于 2012-08-12T19:54:16.037 に答える
0

にバグがあります

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

たとえば、文字列の場合

Hello\n
World\n

のポイントでのループ反復のi == 10場合、skipはすでに1であり(\n前に最初に遭遇したため)、に書き込みを行っていますがtiles[10 + 1]tiles10個の要素を持つ配列としてのみ割り当てられています。

于 2012-08-12T19:57:51.627 に答える
0

変数入力がこの関数に対してローカルである可能性があります。したがって、これから戻った後、メモリは解放されます。したがって、後でこの文字列に対してdeleteを呼び出すと、すでに解放されているメモリを解放しようとします。

于 2012-08-12T20:20:03.287 に答える