2

私が電話したとき、正確には何が起こっているのfree(a)ですか?使用されているメモリが解放されていることはわかっていますが、これは、配列に格納されているデータaにアクセスできなくなったことを意味しますか(したがって、呼び出すことができなくなりますcopyArray)?

int *a = (int *) malloc(sizeof(int) * numberOfInts);
for (i = 0; i < numberOfInts; i++) {
        a[i] = random();
        printf("%d\n", a[i]);
    }
    free(a);
    copyArray(*a++, numberOfInts);
4

7 に答える 7

4

free(a) を呼び出すと、正確には何が起こっているのでしょうか?

これは実装固有です。例として、Linux と glibc では、次のいずれかが発生する可能性があります。

メモリが 128k 以上のブロックに割り当てられた場合、 は新しいメモリ領域を割り当てます (具体的には、のglibcコピー オン ライト)。解放されると、メモリ領域は単純に割り当て解除 ( 'd) されて消えます。さらにアクセスするとクラッシュします。mmap/dev/zeromunmap

割り当てられたメモリが小さかった場合は、ヒープに移動します。ヒープは、固定アドレスから始まる単一のメモリ領域であり、プロセスが縮小または拡大できるサイズです ( を使用sbrk)。

メモリ アロケータは、この領域のどの部分が割り当てられているかを追跡します。初めて何かが割り当てられると、ヒープのサイズが増加し、この新しい領域の最後にメモリが追加されます。

このようなメモリ ブロックを解放すると、ヒープの最後でヒープ サイズが縮小され、メモリが無効になり、その後のアクセスがクラッシュする可能性があります。ただし、アロケータは数バイトだけヒープ サイズを増減することはありません。したがって、その時点では、割り当てのサイズと解放されたブロックの数によって異なります。アクセスできる場合とそうでない場合があります。

10 ブロックのメモリを割り当て、最初の 9 ブロックを解放すると、ヒープに未使用の領域ができてしまいます。終了アドレスを設定することによってのみヒープ サイズを変更できるため、実際には何もできません。メモリは引き続き有効であり、アクセスは引き続き機能します。おそらく元のデータもそこにあり、何も起こらなかったかのように続行できます。

ただし、新しいメモリが割り当てられると、mallocはそれをこの未使用領域に配置しようとするため、他のデータが元のメモリを上書きします。解放された配列に int を設定すると、プログラムのまったく関係のない部分でポインターが上書きされる可能性があり、陽気さとデバッグが続きます。

tl;dr: 解放されたメモリにアクセスしないでください!

于 2013-02-20T18:20:06.777 に答える
1

はい、まさにその通りです。free()問題のメモリを呼び出すとすぐに、オペレーティング システムで使用するために返されます。まだ機能しているように見えるかもしれませんが、未定義の動作を引き起こしています。

于 2013-02-20T17:52:20.153 に答える
1

解放されたメモリ ロケーションにはアクセスしないでください。はい、それらの場所に保存されているデータにはアクセスできなくなります。ただし、解放された場所にアクセスすると、未定義の動作が発生します。

于 2013-02-20T17:52:45.647 に答える
1

しかし、これは、配列 a に格納されているデータにアクセスできなくなったことも意味しますか?

はい - より正確には、それにアクセスする (つまり、無効なポインターを逆参照する) と、未定義の動作が発生するため、プログラムは何でも実行できます(おそらくクラッシュを含む)。

于 2013-02-20T17:52:48.563 に答える
0

'malloc'を使用している場合、aが指すメモリのブロックを動的に割り当てています。通常、実装固有ですが、動的に割り当てられたメモリはヒープに格納されます。freeを呼び出さないと、スコープ外になったときにメモリリークが発生します。

によってポイントされた、作成したメモリのブロックは、freeの呼び出し後に使用できなくなります。これは非常に予測できない動作をし、セグメンテーション違反を引き起こす可能性があります。

于 2013-02-20T17:56:12.503 に答える
0

メモリが解放されると、何が含まれているかを推測することはできません。したがって、今後はアクセスしないでください。

于 2013-02-20T17:52:35.403 に答える
0

これを呼び出すfree(a)と、メモリに再利用のフラグが立てられたことを意味します。したがって、配列への書き込みa引き続き機能しますが、未定義の動作です。後で通知されずに上書きされる可能性があります。

malloc()次に、Cの戻り値をキャストしないでください。

これを行う:

int *a = malloc(sizeof(*a) * numberOfInts);

また、C99 では、これを行うことができる VLA の規定があります。

printf("Enter array length: ");
scanf("%d",&numberOfInts);
int a[numberOfInts];

これらのアレイの割り当てを手動で解除する必要はありません。ただし、VLA の長さには制限があることに注意してください。

于 2013-02-20T17:54:40.613 に答える