【问题标题】:Linked List value changes in gdbgdb 中的链表值更改
【发布时间】:2014-05-15 05:59:18
【问题描述】:

我有一个如下所示的 C 链表:

typedef struct Node {
    struct Node *child;
    void *value;
} Node;

typedef struct LinkedList {
    Node *head;
} LinkedList;

为了测试一切是否正常,我有一个主程序,它逐行读取文件,并将每一行存储在以下节点中。然后,一旦文件到达末尾,我会遍历链表并打印所有行。

但是,当我测试它时,它只打印空行,除了文件中的最后一行,它可以正常打印。此外,尽管所有字符串在存储在节点中之前都经过 malloc 处理,但我得到一个“指针处于空闲状态,但未分配错误”。我在 gdb 中进行了相当广泛的研究,似乎无法弄清楚我做错了什么。也许其他人可以在这里帮助我?这是我的其余代码:

int main(int argc, char **argv) {
    if (argc>1) {
        FILE *mfile = fopen(argv[1], "r");
        if (mfile!=NULL) {
            char c;
            char *s = (char*) malloc(1);
            s[0] = '\0';
            LinkedList *lines = (LinkedList*) malloc(sizeof(LinkedList));
            while ((c=fgetc(mfile))!=EOF) {
                if (c=='\n') {
                    setNextLine(lines, s);
                    free(s);
                    s = (char*) malloc(1);
                    s[0] = '\0';
                }
                else s = append(s, c);
            }
            if (strlen(s)>0) {
                setNextLine(lines, s);
                free(s);
            }
            fclose(mfile);
            printList(lines);
            LLfree(lines);
        } else perror("Invalid filepath specified");
    } else perror("No input file specified");
    return 0;
}

void setNextLine(LinkedList *lines, char *line) {
    struct Node **root = &(lines->head);
    while (*root!=NULL) root = &((*root)->child);
    *root = (Node*) malloc(sizeof(Node));
    (*root)->child = NULL;
    (*root)->value = line;
}

char *append(char *s, char c) {
    int nl = strlen(s)+2;
    char *retval = (char*) malloc(nl);
    strcpy(retval, s);
    retval[nl-2] = c;
    retval[nl-1] = '\0';
    free(s);
    return retval;
}

void printList(LinkedList *lines) {
    Node *root = lines->head;
    while (root!=NULL) {
        char *s = (char*) root->value;
        printf("%s \n", s);
        root = root->child;
    }
}

void LLfree(LinkedList *list) {
    if (list->head!=NULL) NodeFree(list->head);
    free(list);
    return;
}

void NodeFree(Node *head) {
    if (head->child!=NULL) NodeFree(head->child);
    free(head->value);
    free(head);
    return;
}

【问题讨论】:

  • 与您的问题无关,但对于append 功能,您确实了解realloc
  • 另外,there's no need to cast the return value of malloc() in C,最好不要这样做。
  • 可能与您的问题有关,您没有初始化您分配的LinkedList 结构,这意味着head 将具有不确定的值(它看起来是随机的)。访问这个未初始化的成员将导致undefined behavior
  • “指定的文件路径无效”并不是一个特别有启发性的错误消息。试试perror(argv[1])
  • 您可能希望使用 Valgrind (valgrind.org) 等内存检查器运行代码。

标签: c string linked-list malloc free


【解决方案1】:

代码中似乎有几处可以更改。 也许最有可能提供帮助的是内存释放不当。

变化:

                setNextLine(lines, s);
                free(s);
                s = (char*) malloc(1);

到:

                setNextLine(lines, s);
//              free(s);
                s = (char*) malloc(1);

指针“s”仍然指向刚刚分配给前一个节点的“值”的内容。因此,调用“free(s)”实际上是在释放节点的“值”。

【讨论】:

    【解决方案2】:

    尝试这样做

    void NodeFree(Node *head) 
        if (head->child!=NULL) 
    
            NodeFree(head->child);
    
    
        free(head->value);
        free(head->child);
        free(head);
        head->value = NULL;
        head->child = NULL;
        head = NULL;
        return;
    }
    

    【讨论】:

      【解决方案3】:

      setNextLine() 函数将 's' 指针附加到节点值,然后在 while 循环中调用之后释放相同的指针。
      这就是为什么当NodeFree() 试图释放head->value 时你会得到一个双重释放错误。 而你得到最后一行的事实可能只是因为's'指向最后一行的地址(它像前面的所有行一样被释放)仍然没有使用,尽管它不再分配给你的指针。
      您应该复制 setNextLine() 中 's' 指向的行,以便您可以在其余行中使用 's' 指针。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-08-12
        • 1970-01-01
        • 2013-03-04
        • 1970-01-01
        • 2021-07-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多