3

サイズが5428x5428の2D配列があり、対称配列です。しかし、コンパイル中に、配列サイズが大きすぎるというエラーが表示されます。誰かが私に方法を提供できますか?

4

3 に答える 3

4

この配列は、プログラム スタック メモリに対して大きすぎます。これはエラーです。

int main()
{
    double arr[5428][5428]; // 8bytes*5428*5428 = 224MB

    // ...
    // use arr[y][x]
    // ...

    // no memory freeing needed
}

動的配列割り当てを使用します。

int main()
{
    int i;
    double ** arr;

    arr = (double**)malloc(sizeof(double*)*5428);
    for (i = 0; i < 5428; i++)
        arr[i] = (double*)malloc(sizeof(double)*5428);

    // ...
    // use arr[y][x]
    // ...

    for (i = 0; i < 5428; i++)
        free(arr[i]);
    free(arr);
}

または、サイズのプレーン配列を割り当てMxNて使用しますptr[y*width+x]

int main()
{
    double * arr;
    arr = (double*)malloc(sizeof(double)*5428*5428);

    // ...
    // use arr[y*5428 + x]
    // ...

    free(arr);
}

または組み合わせた方法を使用します:

int main()
{
    int i;
    double * arr[5428];  // sizeof(double*)*5428 = 20Kb of stack for x86
    for(i = 0; i < 5428; i++)
        arr[i] = (double)malloc(sizeof(double)*5428);

    // ...
    // use arr[y][x]
    // ...

    for(i = 0; i < 5428; i++)
        free(arr[i]);
}
于 2012-04-20T16:46:03.193 に答える
1

ローカル変数を作成すると、それらはサイズが制限されたスタックに置かれます。あなたはその限界を突破しています。

配列をヒープに置きたいとします。これは、システムが持つすべての仮想メモリです。つまり、最近のシステムではギグとギグです。それを管理するには2つの方法があります。1 つは、k06a の回答のように配列を動的に割り当てることです。malloc() またはプラットフォーム固有のアロケーター関数 (Windows では GlobalAlloc() など) を使用します。2 つ目は、関数の外部で、配列をグローバルまたはモジュールの静的変数として宣言することです。

グローバルまたは静的を使用すると、このメモリがプログラムの存続期間全体にわたって割り当てられるという欠点があります。また、ほとんどの人は原則としてグローバルを嫌っています。一方、2 次元配列構文「array[x][y]」などを使用して、配列要素にアクセスできます... array[x + y * width] を実行するよりも簡単です。 "x + y * width" と "x * height + y" のどちらを実行する必要があるかを覚えておく必要はありません。

于 2012-04-20T16:59:05.113 に答える
1

配列が大きくなった場合、いくつかの解決策があります。あなたにとって良いものは、あなたが実際に何をしているかに大きく依存します.

考えてもらうためにいくつか挙げてみます。

  1. メモリを追加購入します。

  2. 配列をスタックからヒープに移動します。

    スタックには、ヒープよりも厳しいサイズ制限があります。

  3. 配列の一部をシミュレートします (あなたは対称であると言うので、データの 1/2 のすぐ下が冗長です)。

    あなたの場合、配列は対称であるため、配列を使用する代わりに、「シミュレートされた配列」を使用します

    int getArray(array, col, row);
    void setArray(array, col, row, value);

    ここで、配列は左下半分と対角線のみを保持するデータ構造です。次に、getArray(..) は、列が行より大きいかどうかを判断し、大きい場合は戻ります (逆のエントリに注意してください)。getArray(array, row, col); これにより、対称的な両側を実際に保持する必要なく、配列の対称プロパティが活用されます。

  4. 「値を保持する項目のみ」のリスト (またはツリーまたはハッシュ テーブル) を使用して配列をシミュレートします。

    これは、多数のゼロ (または空の) 値を保持するためにメモリを割り当てる必要がなくなるため、スパース配列では非常にうまく機能します。誰かが設定されていない値を「検索」した場合、コードはそのエントリに値が設定されていないことを「発見」し、実際には配列に格納されずに「ゼロ」または空の値を返します。

繰り返しますが、詳細がなければ、どのようなソリューションが最善のアプローチであるかを知ることは困難です。

于 2012-04-20T16:39:25.803 に答える