我目前正在修补C中的二叉树,但我遇到了一个我自己似乎无法解决的问题。我使用Eclipse Mars作为我的IDE。
该项目的基本思想是拥有一个由treeNodes组成的二叉树。这些节点是结构体并且在(struct Books)中包含一个结构,因此有两个单独的用于treeNode和books的库。
这些是有问题的结构:
树节点:
struct TreeNode {
struct Book *book;
unsigned long key;
struct TreeNode *left;
struct TreeNode *right;
};
图书:
struct Book {
unsigned long ISBN;
char* author_name;
char* book_title;
};
现在,节点创建得很好,插入/打印功能也很好用。但是,我也有一个clear()函数,它应该释放任何以前分配的内存。 Malloc仅在new_xxx()函数中调用:
struct TreeNode *new_tree_node(unsigned long ISBN, char *author, char *title) {
//Creating and allocating the new TreeNode
struct TreeNode *new_tree_node;
new_tree_node = (struct TreeNode*) malloc(sizeof(struct TreeNode));
//Creating the book
struct Book *new_Book = newBook(ISBN, author, title);
new_tree_node->book = new_Book;
new_tree_node->left = NULL;
new_tree_node->right = NULL;
new_tree_node->key = ISBN;
return new_tree_node;
}
和newBook():
struct Book *newBook(unsigned long ISBN_nr, char *author_name, char *book_title) {
//Creating and allocating the Book
struct Book *new_Book;
new_Book = (struct Book*) malloc(sizeof(struct Book));
//Assigning Values
new_Book->ISBN = ISBN_nr;
new_Book->author_name = author_name;
new_Book->book_title = book_title;
return new_Book;
}
现在,当我尝试运行clear()函数时,我会收到一个" SIGABRT:Aborted"一旦我尝试释放TreeNode并且进程停止,就会发出信号。 Eclipse也会返回:
"No source available for "raise() at 0x75ffff7a4bcc9".
最初我认为这是因为我的系统无法找到标准功能之一,但控制台也打印出来:
*** Error in /home/max/workspace/bst_2/Debug/bst_2': double free or corruption (out): 0x00007fffffffe030 ***
让我相信代码中确实存在问题。
这是有问题的功能:
void bst_clear(struct TreeNode *tree_node) {
//Clears all nodes recursively
if (tree_node->left != NULL) {
bst_clear(tree_node->left);
}
if (tree_node->right != NULL) {
bst_clear(tree_node->right);
}
tree_node->key = NULL;
tree_node->book = NULL;
free((void*) tree_node);
return;
}
有趣的是,这只会在使用Linux操作系统(Mint 17.1)时发生 - 无论是在VM中还是在双启动系统中。我的主要操作系统,Windows 7 64位,编译运行没有任何问题,完全完成整个过程。
我不确定代码是否确实存在问题(绝对可能是这种情况,我还是新手),或者我的操作系统是否确实混乱了。但由于这种情况发生在虚拟机和实际系统中,它可能与丢失的系统库无关(我猜)。
那么,有没有人知道这里发生了什么?
编辑:valgrind输出:
==2946== Invalid free() / delete / delete[] / realloc()
==2946== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2946== by 0x4008D3: bst_clear (booktree.c:84)
==2946== by 0x400884: bst_clear (booktree.c:73)
==2946== by 0x400884: bst_clear (booktree.c:73)
==2946== by 0x400D17: main (main.c:66)
==2946== Address 0xfff000030 is on thread 1's stack
==2946==
==2946== Invalid free() / delete / delete[] / realloc()
==2946== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
...
==2946==
==2946==
==2946== HEAP SUMMARY:
==2946== in use at exit: 128 bytes in 4 blocks
==2946== total heap usage: 10 allocs, 10 frees, 280 bytes allocated
==2946==
==2946== LEAK SUMMARY:
==2946== definitely lost: 128 bytes in 4 blocks
==2946== indirectly lost: 0 bytes in 0 blocks
==2946== possibly lost: 0 bytes in 0 blocks
==2946== still reachable: 0 bytes in 0 blocks
==2946== suppressed: 0 bytes in 0 blocks
==2946== Rerun with --leak-check=full to see details of leaked memory
错误多次出现 - 有问题的行是free()命令 - 第73行只是递归函数调用。
现在,如果我做对了,我试图释放堆栈中的对象 - 只读内存,对吧?我唯一能想到的是struct声明,它可能包含静态元素?
我还想指出,在Windows机器上运行时存在ZERO问题 - 是否有人知道原因?
编辑2:
这就是节点的创建方式:
char* root_author;
char* root_title;
root_author = "A B C\0";
root_title = "ABC\0";
struct TreeNode *root;
root = new_tree_node(579610, root_author, root_title);
char* n1a;
char* n1t;
n1a = "B C D";
n1t = "BCD";
struct TreeNode *n1 = new_tree_node(406759, n1a, n1t);
bst_insert(root, n1);
这是insert()函数:
void bst_insert(struct TreeNode *tree_node, struct TreeNode *new_node) {
if (new_node->key < tree_node->key) {
//If the key is smaller -> insert left
if (tree_node->left == NULL) {
//There is no left node yet
tree_node->left = new_node;
return;
} else
bst_insert(tree_node->left, new_node); //There is a node -> pass it on
}
else {
//The key is larger -> right
if (tree_node->right == NULL) {
//There is no left node yet
`enter code here`tree_node->right = new_node;
return;
} else
bst_insert(tree_node->right, new_node); //There is a node -> pass it on
}
}