我有一个C链表,看起来像这样:
typedef struct Node {
struct Node *child;
void *value;
} Node;
typedef struct LinkedList {
Node *head;
} LinkedList;
为了测试一切是否正常工作,我有一个主程序,它从文件中逐行读取,并将每行存储在下面的Node中。然后,一旦文件结束,我遍历链表并打印所有行。
然而,当我测试它时,它只打印空行,除了文件中的最后一行,它被正常打印。此外,尽管所有字符串在存储到节点之前都进行了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] = ' ';
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] = ' ';
}
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] = ' ';
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;
}
看起来代码中有一些东西可以修改。也许最有可能帮助的是内存不正确释放。
改变:
setNextLine(lines, s);
free(s);
s = (char*) malloc(1);
:
setNextLine(lines, s);
// free(s);
s = (char*) malloc(1);
指针's'仍然指向刚刚分配给前一个节点的'值'。因此,调用'free(s)'实际上是释放节点的'值'。
试试
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;
}
setNextLine()
函数将's'指针附加到节点值上,然后在while循环调用后释放相同的指针。
这就是为什么当NodeFree()
试图释放head->value
时,你会得到双自由故障。事实上,你得到最后一行可能只是因为最后一行的's'指向的地址(像之前的所有行一样被释放)仍然未被使用,尽管它不再分配给你的指针。
您应该复制setNextLine()
中's'指向的行,以便您可以使用's'指针处理其余行。