我正在尝试在C中实现一个n-ary树。运行它时出现以下错误:
sibling(1143,0x7fff7e925000) malloc: *** error for object 0x7f946b4032c8: incorrect checksum for freed object - object was probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
我不确定导致错误的原因。正如它所说,似乎我正在写一个被释放的对象。但在我的代码中,我没有释放任何分配的内存。我很新闻,非常困惑我。我尝试用gdb进行调试,它说错误是由printTree()引起的;在main中调用我递归尝试打印树。希望你能帮助我理解这个问题: - )。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char *name;
unsigned int utility;
unsigned int probability;
} Child;
typedef struct {
unsigned int level;
unsigned int player;
unsigned int nChildren;
Child *children;
} Data;
typedef struct sNaryNode{
Data *data;
struct sNaryNode *kid;
struct sNaryNode *sibling;
} NaryNode;
NaryNode* createNode(Data data){
NaryNode *newNaryNode = malloc(sizeof (NaryNode*));
newNaryNode->sibling = NULL;
newNaryNode->kid = NULL;
newNaryNode->data = &data;
return newNaryNode;
}
NaryNode* addSibling(NaryNode* n, Data data){
if(n == NULL) return NULL;
while(n->sibling)
n = n->sibling;
return (n->sibling = createNode(data));
}
NaryNode* addChild(NaryNode* n, Data data){
if(n == NULL) return NULL;
else if(n->kid)
return addSibling(n->kid, data);
else
return (n->kid = createNode(data));
}
void printTree(NaryNode* n) {
if(n == NULL) return;
if(n->sibling) {
printf("%u %u %u %u %u %s", n->data->level, n->data->player, n->data->nChildren, n->data->children[0].probability, n->data->children[0].utility, n->data->children[0].name);
printTree(n->sibling);
}
else if(n->kid) {
printf("%u %u %u %u %u %s", n->data->level, n->data->player, n->data->nChildren, n->data->children[0].probability, n->data->children[0].utility, n->data->children[0].name);
printTree(n->kid);
}
else {
printf("The tree was printed\n");
}
}
int main(void) {
NaryNode *root = calloc(1, sizeof(NaryNode));
Data data;
data.level = 1;
data.player = 1;
data.nChildren = 2;
data.children = calloc(data.nChildren, sizeof data.nChildren);
data.children[0].probability = 50;
data.children[0].utility = 1;
data.children[0].name = "Kom med det første tilbud (anchor)";
data.children[1].probability = 50;
data.children[1].utility = 1;
data.children[1].name = "Afvent modspilleren kommer med første tilbud";
*root = *createNode(data);
int i = 0;
for(i=0; i<root->data->nChildren; i++) {
addChild(root, data);
}
printTree(root);
}
答案 0 :(得分:3)
您的代码中存在各种错误。
分配大小不正确的内存块:
data.children = calloc(data.nChildren, sizeof data.nChildren);
data.children
是一个Child
结构数组,但由于sizeof(unsigned int)
是{{1},您需要分配大小等于data.nChildren
的结构}}
获取临时变量的地址并将其存储起来供以后使用:
unsigned int
NaryNode* createNode(Data data){
newNaryNode->data = &data;
}
中的{p> data
仅在函数运行时存在:在这种情况下,您将获取局部变量createNode
的地址并将其存储在您将返回以供以后使用的结构。这是一个非常糟糕的主意,因为这个指针将引用一个在函数返回后不再存在的对象。
请注意,您不需要在当前代码中将data
对象的副本传递到Data
,因为实际上只有一个createNode
对象整个计划。因此,您可以将Data
的原型更改为createNode
,并传递您在createNode(Data* data)
中创建的Data
结构的地址。然而,做更多涉及的事情,需要深入复制结构,我认为。
错误地管理对象&#39;寿命。
main
NaryNode *root = calloc(1, sizeof(NaryNode));
*root = *createNode(data);
会返回createNode
。但是,您实际上从未将其分配给NaryNode*
,以便以后可以将其释放。相反,指向函数返回的对象的指针仅在NaryNode*
调用期间已知,并且稍后不可避免地丢失。但是,由于取消引用它并将其复制到*root = *createNode(data)
中,您确实保留了对象的内容:但是,从root
返回的对象本身会丢失且无法恢复,除非指向它仍然存在于树中。