[英]Free linked list containing structures containing structures
這是給學校的。
我正在研究 Unix 'ls' 命令的實現。 為此,我每次讀取目錄時都使用鏈表(因此,如果未設置 -R 選項,則僅使用一次)。 為此,我必須使用我們必須在以前的項目中編碼的鏈表函數和節點(或元素,我不確定正確的名稱是什么。)。 這些節點看起來像這樣:
typedef struct s_list
{
void *content;
size_t content_size;
struct s_list *next;
}t_list;
在我的 ls 程序中,我使用這些來存儲我列出的目錄中的每個文件的名稱和統計信息,通過 stat() 函數獲得。 所以我的 t_list 的“內容”指針是這個結構:
typedef struct s_entry
{
char *filename;
struct stat filestat;
}t_entry;
一切正常,我遇到的唯一問題是 Valgrind 告訴我,用於分配這些 t_entry 結構的 malloc() 存在泄漏。 所以我想我是在錯誤地釋放它們......我是這樣做的:
void free_list(t_list *entries)
{
t_list *n_node;
if (!entries)
return ;
while (entries)
{
n_node = entries->next;
free(entries->content);
free(entries);
entries = n_node;
}
}
我猜僅僅釋放 *content 指針是不夠的,但我嘗試了其他方法,但它不起作用。 如果我嘗試自由喜歡
free(entries->content->filename);
例如,它不起作用並且內容是空指針這一事實在我試圖解決問題的某些方面似乎是一個問題,但這就是我們必須對這些鏈表函數進行編碼的方式。
如果有人能給我一個關於如何正確釋放這些列表的提示,那就太棒了,因為我真的堅持這個。 提前致謝。 對不起,如果我的英語或解釋不夠清楚。
ps:以防萬一,整個項目(遠未完成)可以在這里找到: https : //github.com/Zestx/ft_ls
您需要轉換數據,以便編譯器知道在哪里可以找到結構體成員,這是一個完整的示例:
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
typedef struct s_list
{
void *content;
size_t content_size;
struct s_list *next;
}t_list;
typedef struct s_entry
{
char *filename;
struct stat filestat;
}t_entry;
int main(void)
{
t_list *foo = malloc(sizeof *foo);
t_entry *bar = malloc(sizeof *bar);
bar->filename = malloc(10);
foo->content = bar;
free(((t_entry *)foo->content)->filename);
free(foo->content);
free(foo);
return 0;
}
如果您有目錄中每個文件的ls
條目列表,其中content
是指向包含文件名和stat
信息的已分配t_entry
的指針,例如
typedef struct s_list {
void *content;
size_t content_size;
struct s_list *next;
} t_list;
和
typedef struct s_entry {
char *filename;
struct stat filestat;
} t_entry;
freelist (t_list *head)
函數需要遍歷每個節點,並且:
free
每個t_entry
內分配的filename
;free
分配的t_entry
; 最后free
t_list
節點本身。您可以執行類似於以下操作:
void freelist (t_list *head)
{
t_list *node = head; /* temporary node to iterate list */
/* (you could use head, but don't) */
while (*node) {
t_list *victim = node; /* pointer to current node to free */
t_entry *entry = node->content; /* pointer to content */
free (entry->filename) /* free content->filename */
free (entry); /* free t_entry struct itself */
node = node->next; /* advance before freeing victim */
free (victim); /* free current t_list node (victim) */
}
}
注意上面,您可以簡單地使用head
進行迭代,而不是使用node
,因為freelist
收到一個無論如何都不會改變列表地址的副本——並且因為完成后將沒有列表,但這是一個更好的習慣使用臨時節點來迭代列表(在任何函數中),這樣在處理實際列表地址(例如參數是t_list **
)或指針副本(參數是t_list *
)。
仔細檢查一下,如果您還有其他問題,請告訴我。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.