C語言如何正確的free一個結構體指針?
struct Student{
char* name;
int age;
}
場景:
因為需要動態分配了多個Student的實例(malloc),然後每個實例的name也是由malloc動態分配的
問題一:
所以怎麼才能把所有申請的內存都釋放而不產生內存泄漏?
問題二:
假如不那麼複雜,單單free一個Student的實例(name還沒有動態分配到內存),是不是把age和name這兩個變數都收回了?
問題三:
如果是上面假設的那樣的話(free一個實例後age和name這兩個變數都被清理了)
假如name 動態分配到了內存後,再free Student的實例豈不是造成了內存泄漏!?
場景:
因為需要動態分配了多個Student的實例(malloc),然後每個實例的name也是由malloc動態分配的
不。malloc不能分配任何「實例」。malloc分配的是一塊指定大小的內存。你讓一個指針指向這個內存並且通過這個指針訪問這塊內存,是把這塊內存「當作」這個指針指向的類型的一個或多個實例。name也一樣。
問題一:
所以怎麼才能把所有申請的內存都釋放而不產生內存泄漏?
用完一個釋放一個。這裡,name指向的內存如果還沒free,那麼整個結構體指針指向的內存也不能算用完,對吧。
問題二:
假如不那麼複雜,單單free一個Student的實例(name還沒有動態分配到內存),
是不是把age和name這兩個變數都收回了?
free的是一塊內存,它的大小是malloc時指定的。那時指定了多大就free多大。free之後的內存會在某個時候被malloc再次分配。
問題三:
如果是上面假設的那樣的話(free一個實例後age和name這兩個變數都被清理了)
age和name不是變數,它們是結構體成員,是Student這個結構體裏的一個「位置」。free也不會「清理」任何東西,它只是告訴內存分配機制某段內存已經不再被使用了,現在是沒有被分配的狀態。
假如name 動態分配到了內存後,再free Student的實例豈不是造成了內存泄漏!?
某個Student指針所指向的內存被free後,這塊內存裏的所有位置,當然也包括name位置,就不應該再去讀取了。如果另一塊malloc所分配的內存的地址被保存在name位置裏,也就不能讀取了,當然也就不能free了。但是如果你在其他位置保存了這塊內存的地址,你一樣可以通過讀取那個位置裏保存的地址來free這塊內存。
你好,總結一下你的問題:C語言中誰申請了內存誰就釋放,沒有申請堆內存,是不需要釋放的,2段代碼足可以說明問題。
- 第一種情況:name指針也申請了堆內存,此時需要釋放name指向的內存後再釋放結構體節點指針
Student *p = (Student*)malloc(sizeof(Student)); // 申請內存:結構體一個節點
if (p == nullptr) {
return 0;
}
p-&>name = (char*)malloc(sizeof(char) * kNameLen); // 申請內存:name 指針指向多大可以使用的內存
p-&>age = 22;
strncpy(p-&>name, "lilie", strlen("lilie"));
// 釋放:先釋放p-&>name
free(p-&>name);
// 再釋放 p
free(p);
p = nullptr;
第二種情況:name指針沒有申請堆內存,我們只需要釋放結構體節點指針指向的內存就可以了。
Student *p = (Student*)malloc(sizeof(Student)); // 申請內存:結構體一個節點
if (p == nullptr) {
return 0;
}
p-&>age = 22;
// 無需釋放p-&>name所指向內存,因為壓根就沒有申請內存,只需要釋放 p
free(p);
p = nullptr;
最後附上手繪圖