中止陷阱6 malloc

时间:2016-12-04 13:56:46

标签: c

我正在尝试在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);
}

1 个答案:

答案 0 :(得分:3)

您的代码中存在各种错误。

  1. 分配大小不正确的内存块:

    data.children = calloc(data.nChildren, sizeof data.nChildren);

    data.children是一个Child结构数组,但由于sizeof(unsigned int)是{{1},您需要分配大小等于data.nChildren的结构}}

  2. 获取临时变量的地址并将其存储起来供以后使用:

    unsigned int

    NaryNode* createNode(Data data){ newNaryNode->data = &data; }中的{p> data仅在函数运行时存在:在这种情况下,您将获取局部变量createNode的地址并将其存储在您将返回以供以后使用的结构。这是一个非常糟糕的主意,因为这个指针将引用一个在函数返回后不再存在的对象。

    请注意,您不需要在当前代码中将data对象的副本传递到Data,因为实际上只有一个createNode对象整个计划。因此,您可以将Data的原型更改为createNode,并传递您在createNode(Data* data)中创建的Data结构的地址。然而,做更多涉及的事情,需要深入复制结构,我认为。

  3. 错误地管理对象&#39;寿命。

    main

    NaryNode *root = calloc(1, sizeof(NaryNode)); *root = *createNode(data);会返回createNode。但是,您实际上从未将其分配给NaryNode*,以便以后可以将其释放。相反,指向函数返回的对象的指针仅在NaryNode*调用期间已知,并且稍后不可避免地丢失。但是,由于取消引用它并将其复制到*root = *createNode(data)中,您确实保留了对象的内容:但是,从root返回的对象本身会丢失且无法恢复,除非指向它仍然存在于树中。