【问题标题】:Destructor function doesnt work as intended and I get a segmentation fault (C)析构函数没有按预期工作,我得到一个分段错误(C)
【发布时间】:2020-04-19 21:42:56
【问题描述】:

我目前正在做一些家庭作业,我需要一些帮助。

函数free_lnode 触发一次Segmentation fault(core dumped)。在核心被转储之前,我收到了我正在尝试释放未知指针的消息。

我已缩小问题范围并在下面的代码中对其进行了注释,但是我不知道如何修复 free_lnode 函数中的错误。

函数free_lnodefree_node的实现需要通过递归来完成!!!

注意: 我的代码使用了教授库中的 2 个函数:

  • xcalloc 的工作方式与 calloc 相同,只是它自己检查 NULL*
  • s_copystrcpy 类似,但副本是动态分配的

    这些函数不是错误的原因,而是在析构函数中处理。

提前致谢,新年快乐!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


typedef struct Node {
    char* value;
    int count;
    struct Node *next;
} Node;

typedef struct WishList {
    Node *first;
    char *name;
} WishList;

typedef struct Lnode{
    WishList* value;
    struct Lnode* next;
} Lnode;

/********* Constructor functions ********/


Lnode* new_lnode(WishList* value, Lnode* next){
    Lnode* lnode = xcalloc(1, sizeof(Lnode)); //same as calloc only checks for NULL itself
    lnode->value = value;
    lnode->next = next;
    return lnode;
}


WishList* new_wish_list(char* name, Node* node) {
    WishList* list = xcalloc(1, sizeof(WishList)); //same as calloc only checks for NULL itself
    list->name = s_copy(name); // s_copy performs dynamic allocation
    list->first = node;
    return list;
}

Node* new_node(char* value, int count, Node* next) {
    Node* node = xcalloc(1, sizeof(Node)); //same as calloc only checks for NULL itself
    node->value = s_copy(value); // s_copy performs dynamic allocation
    node->count = count;
    node->next = next;
    return node;
}

/********* Destructor functions ********/

// Recursive destructor function ==> Works
void free_node(Node* node){
    if(node->next){
      free(node->value);
      free_node(node->next);
    }

    if(node->next == NULL){
      free(node->value);
    }
    free(node);
}

// destructor function ==> Works
void free_wish_list(WishList* list){
    free_node(list->first);
    free(list->name);
    free(list);
}

// Recursive destructor function => TODO: DEBUG
void free_lnode(Lnode* lnode){
    if(lnode->next){
      printf("DEBUG\n"); // is triggered twice before segmentation is dumped
      free_wish_list(lnode->value); //fails to free second wishlist, Console output: trying to free an unknown pointer <some memory location>, segmentation fault (core dumped)
      printf("DEBUG\n"); // is only triggered once before segmentation dumped
      free_lnode(lnode->next);
    }
    if(lnode->next == NULL){
      free_wish_list(lnode->value);
    }
    free(lnode);
}
/************************************/


int main(){

  Node* a = NULL;
  a = new_node("test1", 1, NULL);
  Node* b = new_node("test2", 1, a);
  Node* c = new_node("test3", 1, b);
  Node* d = new_node("test4", 1, c);
  Node* e = new_node("test5", 1, d);

  WishList* usage_test = new_wish_list("Epic_Test", e);

  Node* f = NULL;
  f = new_node("test6", 1, NULL);
  Node* g = new_node("test7", 1, f);
  Node* h = new_node("test8", 1, g);
  Node* k = new_node("test9", 1, h);

  WishList* usage_test2 = new_wish_list("Epic_Test2", k);

  Lnode* new_long_node = new_lnode(usage_test, usage_test2);
  free_lnode(new_long_node);

  return 0;
}

【问题讨论】:

  • 在您的 free_node 函数中,我可以看到 3 个 free() 调用。你知道是哪一个导致了段错误吗?您应该尝试使用一些调试器来找出问题(例如 gdb、valgrind)
  • @Phantom 您的建议是正确的,我进一步缩小了问题范围:free_node 调用 free_node 时出现了段错误。
  • 这个错误应该已经被编译器警告捕获了。
  • @Phantom 您的建议是正确的,我进一步缩小了问题的范围:if( node-&gt;next == NULL) {free(node-&gt;value);} 调用中的free_node 发生了段错误。程序成功释放了usage_test,但是当第二个节点usage_test2 被发送进来时,它释放了所有节点,但是当它退出递归时,它在if( node-&gt;next == NULL) {free(node-&gt;value);} 调用处触发了一个段错误。
  • 你可以使用strdup()来分配一个字符串的副本。

标签: c pointers recursion linked-list free


【解决方案1】:

这里的代码:

Lnode* new_long_node = new_lnode(usage_test, usage_test2);
free_lnode(new_long_node);

是错误的,很容易弄清楚,因为它发出了一个非常明显的警告:

test.c: In function ‘main’:
test.c:105:3: warning: passing argument 2 of ‘new_lnode’ from incompatible pointer type [enabled by default]
test.c:25:8: note: expected ‘struct Lnode *’ but argument is of type ‘struct WishList *’

所以你链接你的节点是错误的。只是从你的 API 推断,我认为你想做这样的事情:

Lnode* new_long_node1 = new_lnode(usage_test, NULL);
Lnode* new_long_node2 = new_lnode(usage_test2, new_long_node1);
free_lnode(new_long_node2);

哦,你的 s_copy 函数实际上是 strdup 而不是 strcopy

【讨论】:

  • 感谢分配!这实际上解决了我的问题! @dragosht
猜你喜欢
  • 2011-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多