【问题标题】:Free a structure.... I'm not sure if I do it right释放一个结构....我不确定我是否做对了
【发布时间】:2015-01-12 16:55:29
【问题描述】:

我的程序管理结构的链表。

这是我的结构:

typedef struct wagon wagon;
typedef struct wagon{
    wagon *next;
    marchandise_ptr *liste;
    double volume_courant;
}train_ptr;

wagon *next 是指向我的链表的下一个“单元”的指针,marchandise_ptr *list 是指向另一个链表的指针。为了释放我的结构,我按照以下方式进行:

在 int main() 中:

train_ptr *train=creer_un_train(...)//so train is the beginning of my linked list
liberer_train(&train);

我的职能是:

创建一个“马车”

wagon *creer_wagon(marchandise_ptr *liste,double volume_courant){ //it creates a wagon
    assert(volume_courant>=0);
    wagon *wag=malloc(sizeof(wagon));
    if(wag==NULL)
        return NULL;
    wag->next=NULL;
    wag->volume_courant=volume_courant;
    wag->liste=liste;
    return wag;
}

在我的链表末尾添加创建的“wagon”:

train_ptr *ajouter_wagon_a_la_fin_du_train(train_ptr *train,double volume_courant, marchandise_ptr *liste){
    wagon *wag=creer_wagon(liste,volume_courant);
    if(wag==NULL)
        return NULL;
    if(train==NULL)
        train=wag;
    else{
        train_ptr *wag_current=train;
        while(wag_current->next!=NULL)
            wag_current=wag_current->next;
        wag_current->next=wag;
        }
    return train;
}

创建火车:

train_ptr *creer_un_train(unsigned int nombre_de_wagons,marchandise_ptr *liste){
    assert(nombre_de_wagons>=0);
    int i;
    train_ptr *train=NULL;

    for(i=0;i<nombre_de_wagons;i++){
        train=ajouter_wagon_a_la_fin_du_train(train,rand()%10,liste);
        if(train==NULL)
            return NULL;
        }
    return train;
}

免费乘坐火车:

void liberer_train(train_ptr **train){
    train_ptr *p_current = *train;
    while(p_current!=NULL){
                *train = p_current->next;
                p_current->next=NULL;
                free(p_current->liste);
                free(p_current);
                p_current = *train;
    }
}

P.S.:liste 是一个指向链表开头的指针:

typedef struct marchandise marchandise;
typedef struct marchandise{
    double volume;
    double volume_total;
    char nom;
    marchandise *suivant;
}marchandise_ptr;

感谢您的关注! (对不起我的英语,我不是母语人士......:D)

【问题讨论】:

  • 你可以使用 valgrind 来搜索内存泄漏。
  • 我看不到 liste 是什么?它指向哪里
  • Liste 指向另一个链表的 biginning(也由结构组成)
  • 如果p_current-&gt;liste是另一个链表,free(p_current-&gt;liste)只会释放根节点,你就有内存泄漏了。
  • 请注意:typedef struct wagon { wagon *next; marchandise_ptr *liste; double volume_courant; } train_ptr; 使用的类型 wagonstruct wagon 无关,因为它被标记为 C 而不是 C++。如果您使用 C 编译器进行编译,则结构体中需要 struct wagon *next;。此外,通常明智的做法是 (IMNSHO) 为标记和类型使用相同的名称,或者为标记和类型名称使用非常密切相关的名称。那是typedef struct X { … } X; 是有道理的;有些人使用typedef struct xyz_s { … } xyz_t;。但wagontrain_ptr 关系并不密切。

标签: c pointers linked-list structure free


【解决方案1】:

从您的 creer_wagon 函数来看,liste 似乎不应该由 liberer_train 函数释放,因为它不是由 creer_wagon 函数分配的。

按照该逻辑,您调用creer_wagon 的函数应该负责liste 成员,因为在调用函数的范围内您将拥有指向它的有效指针,并且您将面临双重风险liste 成员的free

如果每个train 只需要对liste 有一个引用但不需要修改它,你可以像这样定义你的结构

typedef struct wagon{
    wagon *next;
    const marchandise_ptr *liste;
    double volume_courant;
}train_ptr;

这将防止意外尝试修改或free liste 成员。

如果许多火车可以指向同一个liste,这种设计是有意义的,尽管它增加了struct wagon 用户的责任,因为他们应该负责liste 成员的内存管理。如果是这种情况,我双重推荐const 限定符。

在我看来,无论liste 是否由您分配,这是一种有效的推理方式。

我建议你像这样修复liberer_train函数

void liberer_train(train_ptr **train) {
    train_ptr *p_current = *train;
    train_ptr *suivant   = NULL;
    while (p_current != NULL) {
        suivant = p_current->next;
        free(p_current);        
        p_current = suivant;
    }
    /* make the pointer NULL, so it's not a dangling pointer in the caller function anymore. */
    *train = NULL; 
}

另外,我建议你改变

typedef struct wagon train_ptr;

typedef struct wagon *train_ptr;

typedef struct wagon train;

例如,因为后缀_ptr 让人认为train_ptr x; x 是一个指针,而它不是。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-28
    • 1970-01-01
    • 2011-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-21
    相关资源
    最近更新 更多