我是 C 語言的新手,我試圖了解記憶體分配的基礎知識。在這里,我有兩個產生完全相同結果的函式,但其??中只有一個使用 malloc() 函式,而另一個沒有。
第一個功能
int First()
{
int arr[] = {11, 13, 7, 12, 16};
int length = sizeof(arr) / sizeof(int);
// NOT using malloc
int arr2[length];
// Initialize elements to 0
for (int i=0; i < length; i )
arr2[i] = 0;
// Print results
for (int i = 0; i < length; i )
printf("%d ", arr2[i]);
return 0;
}
第二個功能
int Second()
{
int arr[] = {11, 13, 7, 12, 16};
int length = sizeof(arr) / sizeof(int);
int *arr2;
// Here im using malloc to allocate memory
arr2 = malloc(sizeof *arr2 * length);
// Initialize elements to 0
for (int i=0; i < length; i )
arr2[i] = 0;
// Print results
for (int i = 0; i < length; i )
printf("%d ", arr2[i]);
return 1;
}
這兩個函式都將列印:0 0 0 0 0.
這兩種方法有什么區別?我知道使用 malloc(或 memset)基于變數分配記憶體是正確的方法,但我試圖理解為什么?
謝謝!
uj5u.com熱心網友回復:
區別在于物件的生命周期。基本上它意味著當物件有效并且可以訪問時。
一般來說,生命周期分為三種:
靜止的
物件一直有效
例子:
int* foo(void) {
static int A[10];
return A;
}
陣列A始終有效。它可以安全地從函式中回傳。
自動的
物件從其定義到宣告它的塊的末尾都是有效的
例子:
void foo(void) {
int *p;
{
int A[10];
... A is valid here ...
p = &A[0]; // p points to
*p = 42; // still valid
}
// A is no longer valid
*p = 666; // UB strikes, expect everything
}
永遠不要從函式回傳指向自動物件的指標,因為它們將指向不存在的物件。對此類指標的任何值的使用都會觸發未定義的行為。
動態的
生命周期由程式控制。它從通過malloc()或類似功能分配記憶體開始。它在呼叫free()指向該物件的指標時結束。動態物件只能通過指標訪問。
例子:
int* foo(void) {
int *p;
{
p = malloc(sizeof(int[10])); // p points to an object for 10 ints
*p = 42; // still valid
}
*p = 43; // still valid
return p; // still valid though function has returned
}
int *p = foo();
*p = 44;
free(p); // release
*p = 666; // UB strikes, expect everything
忘記呼叫free()通常會導致記憶體泄漏。
uj5u.com熱心網友回復:
第二個函式有記憶體泄漏,因為動態分配的陣列沒有被釋放。
由于使用可變長度陣列,編譯器有條件地支持第一個函式。此外,如果陣列的大小很大,那么它可能會發生這樣的情況,即不會分配陣列。
并且該函式memset不分配任何內容。
uj5u.com熱心網友回復:
我能想到的區別之一是陣列的大小。在你的第一個函式中,如果你放在sizeof(arr2)最后,你會得到 20。但是在你的第二個函式中,當你放sizeof(arr2)你會得到 8。(指標的大小取決于您的計算機。指標的大小是 64 中的 8 個位元組位模式。在 32 位模式下為 4 個位元組。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/470446.html
