0

重複の可能性:
malloc() の後に範囲外のポインターに書き込んでもエラーが発生しない

2 のみの配列にメモリを割り当てるための非常に基本的なプログラムを試していintsます。intsと の 2 つだけにメモリarray[0]を割り当てていますarray[1]array[2]

#include <stdio.h>

int main(int argc, char *argv[])
{
    int *array;
    int i;
    array = NULL;
    array = malloc(sizeof(int)*2);

    array[0] = 2;
    array[1] = 3;
    array[2] = 4;

    for( i = 0; i<3 ; i++)
    printf("%d\n", array[i]);

    return 0;
}

出力:

 2
 3
 4
4

6 に答える 6

3

理解を深めるために、ここで回答を読んでください

ここで説明されているように、本質的にはメモリの破損です

4ではなく非常に大きな数を使用してみてください。malloc()を呼び出すと、大きなページから小さなメモリチャンクが切り出されるため、エラーが発生します。したがって、チャンクの境界を超えて書き込むことは、必ずしもクラッシュすることを意味するわけではありません。array [4]では、その最初のチャンクに割り当てられたページの境界外に書き込んでいないため、技術的には有効なマップされたアドレスに書き込んでいます。ソース

于 2012-08-16T17:33:53.757 に答える
3

C は自分のものではないメモリへのアクセスを妨げないため、これは機能しているように見えるかもしれません。動作しているように見えても、コードはまだ正しくなく、明日動作しない可能性があります。自分に属していないメモリを読み書きすることで、未定義の動作を呼び出しています。

于 2012-08-16T17:24:48.160 に答える
2

pb2q は完全に正しいです。割り当てられていないメモリにアクセスしていることを確認する 1 つの方法は、次のようにすることです。

array = calloc(sizeof(int) * 2); 
for (i = 0; i < 3; i++)
    printf("%d\n", array[i]);

おそらく次の出力が表示されます。

0
0
*random value*
于 2012-08-16T17:34:43.527 に答える
0

Cはあなたの手を握ろうとしないからです。未割り当てのメモリに対して読み取り/書き込みを行うことはできますが、他のオブジェクトからデータを変更/プルしたり、ガベージデータをプルしたりすることもできます。

配列を作成すると、メモリ内のアドレスへのポインタを取得し、それを好きなように使用できます。メモリを割り当てることにより、配列用に予約したかのように、そのメモリチャンク内に他のオブジェクトが作成されないようにします。ただし、その量を超えることに制限はなく、好きな場所で読み書きできます。これの利点は、かなりのパワーがあり、アドレスを直接操作できることです。欠点は、他のオブジェクトに属するメモリ位置で、プログラムが私の操作情報を非常に簡単に分解する可能性があることです。

これから取り除くべきことは、Cがあなたに大量の力を与え、その力の使用を完全にあなたに任せるということです。

于 2012-08-16T17:32:41.470 に答える
0

の実装はmalloc メモリブロックの前後に情報を配置し、ブロック単位で割り当てる(つまり、割り当て要求を最も近い64バイトに丸める)ため、機能すると思います。mallocedメモリは解放できる必要があり、これにはサイズなどに関する情報が必要です。この情報は、割り当てられたメモリの直前および/または直後に配置されます。

データがチャンクで割り当てられている場合、1つの「ブロック」を完全に埋めたところに到達できる制限があり、読み取りはarray[n]「ブロック」の終わりから外れます。これは次のようにテストできます。

int main() {
    int i;
    char * a;
    for (i = 1; i < 10000; i++) {
        a = malloc(i);
        a[i] = 'x';
        printf("%d %c\n", i, a[i]);
        free(a);
    }
    return 0;
}

それmallocはますます大きなメモリブロックになり、範囲外のセグフォールトをチェックします。私が得る切り捨てられた出力は次のとおりです。

1 x
[...]
58 x
59 x
60 x
61 x
62 x
*** glibc detected *** ./a.out: free(): invalid next size (normal): 0x0a041008 ***
[...]

a = malloc(63); a[63] = 'x';つまり、前に話していたメタデータが破損するため、失敗します。

于 2012-08-16T17:37:46.653 に答える
0

ヒントは次のとおりです。関数でのprintfの使用は避ける必要があります...main()内でのみ使用してください(:

mallocとreallocを使用する場合、Cはintのサイズでメモリを割り当てます。番号を付けるために別の「場所」を割り当てることはありません。発生する唯一のことは、入力したデータのバイトサイズがintと同じである場合です。Cは配列サイズがいっぱいかどうかを教えてくれないので、これは通常起こることです。それに注意してください。

于 2012-08-16T18:15:44.960 に答える