この割り当てでは、malloc()
(_var1
_および_var2
_という名前)を使用して2つのint型変数を割り当て、各変数のアドレス(スタック上のポインターのアドレスとヒープ上のアドレス)、次にfree()
を使用して_var1
_の割り当てを解除し、アドレスを再度出力してから、ヒープ内に_var1
_に別のスペースを割り当て、アドレスを3回印刷します。インストラクターは、_var1
_のヒープアドレスが変更されることになっていることを示しようとしていると思いますが、コードからfree(var1)
を削除しない限り、常に同じままです。インストラクターは同様のデモンストレーションを行いましたが、変数の割り当てを解除するためにfree()
を使用しなかったため、これがどのように機能するかはわかりませんでした。
これが私のコードです:
_#include <stdio.h>
#include <stdlib.h>
void main()
{
int *var1 = (int*)malloc(sizeof(int));
*var1 = 1000;
int *var2 = (int*)malloc(sizeof(int));
*var2 = 2000;
printf("Addresses of var1\n");
printf("Pointer on stack: %p / Heap: %p\n\n", &var1, var1);
printf("Addresses of var2\n");
printf("Pointer on stack: %p / Heap: %p\n\n", &var2, var2);
free(var1);
printf("AFTER DEALLOCATING var1 FROM THE HEAP\n");
printf("Addresses of var1\n");
printf("Pointer on stack: %p / Heap: %p\n\n", &var1, var1);
printf("Addresses of var2\n");
printf("Pointer on stack: %p / Heap: %p\n\n", &var2, var2);
var1 = (int*) malloc(sizeof(int));
*var1 = 1500;
printf("NEW MEMORY ADDRESS ALLOCATED FOR var1\n");
printf("Addresses of var1\n");
printf("Pointer on stack: %p / Heap: %p\n\n", &var1, var1);
printf("Addresses of var2\n");
printf("Pointer on stack: %p / Heap: %p\n\n", &var2, var2);
}
_
このコードにより、次の出力が得られます。
_Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390
Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0
AFTER DEALLOCATING var1 FROM THE HEAP
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390
Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0
NEW MEMORY ADDRESS ALLOCATED FOR var1
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390
Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0
_
ご覧のとおり、ヒープアドレスは、割り当てを解除しても_var1
_の場合は変更されず、_var1
_にメモリスペースを再度割り当てても変更されません。ただし、プログラムからfree(var1)
行を削除すると、_var1
_に2番目のメモリスペースが割り当てられ、ヒープ上のメモリスペースがポイントされます。メモリアドレスは異なります。
_Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390
Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0
AFTER DEALLOCATING var1 FROM THE HEAP
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390
Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0
NEW MEMORY ADDRESS ALLOCATED FOR var1
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000420
Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0
_
(明確にするために、前のコードからfree(var1)
を削除するだけだったので、「AFTER DEALLOCATING var1」セクションには、前のセットとまったく同じヒープアドレスが表示されますが、ヒープアドレスは変更されます3番目のセクションのvar1の。)
ここで何が起こっているのか誰か教えてもらえますか?私が思いつくことができる唯一の論理的な説明は、free()
を使用して_var1
_の割り当てを解除してからアドレスを出力すると、それが指している最後のアドレスを出力するだけであり、 2回目は_var1
_にメモリを割り当てていますが、これは単に前のアドレスを新しい値_var1
_で「埋め戻し」ているだけです。これは意味がありますか?コードにエラーがありますか、それとも変数のメモリの割り当てを解除してから再割り当てするときにCがどのように動作するのですか?
malloc
が、メモリが解放されてから再割り当てされたときに同じアドレスを返すことは完全に正常です。また、異なるアドレスを返すことも正常です。
malloc
呼び出しを変更して、元の割り当てとは異なるサイズを要求すると、malloc
が準備した古いブロックでは新しい要求に十分でない可能性があるため、異なるアドレスを取得する可能性があります。しかし、それらで十分かもしれないので、アドレスは変更されないかもしれません。
ちなみに:
void main()
が正しくありません。 int main(void)
である必要があります。malloc
で割り当てられたオブジェクトがfree
で解放されると、その存続期間は終了します。私が思いつくことができる唯一の論理的な説明は、free()を使用してvar1の割り当てを解除してからアドレスを出力する場合、それが指している最後のアドレスを出力するだけであるということです。
一種の権利。ポインタを解放しても、ポインタの内容にはまったく影響しません。もっと正確に言うと、解放された後の値は不確定です。実際、標準によれば、free
を呼び出す前に行ったアドレスを含むポインターを信頼することさえできません。私の知る限り、ほとんどの場合そうなりますが、信頼することはできません。
標準は言う:
C 2018 6.2.4 2:「ポインターが指す(またはちょうど過ぎた)オブジェクトがその存続期間の終わりに達すると、ポインターの値は不確定になります。」
よくある間違いは、ポインタを適切に解放したかどうかをチェックするためにテストif(ptr == NULL)
を使用することです。これは機能しません。
最初の例では、ヒープを指すために使用されたポインターがfree()
の後のスタックで変更されないままになっている場所の値。ただし、そのアドレスにはアクセスできなくなります。
彼らが変数を再度割り当てるとき、同じアドレスを取得することは不思議ではありません。そのアドレスに適切なサイズの使用可能なセグメントがあるはずだからです。ただし、同じアドレスを取得できるとは限りません。使用可能なアドレスから最適なアドレスは、ライブラリコードによって処理されます。