C:sprintf和递归

时间:2010-05-11 18:40:41

标签: c recursion segmentation-fault printf

在C中,是否可以在sprintf函数中使用递归?出于某种原因,当我这样做时会出现分段错误:

inline char *TreeNode_toString(const TreeNode *node)
{
  char *out;

  if(TreeNode_isExternal(node)) // If the node has no children...
  {
    sprintf(out, "%s:%.2f", node->name, node->distance);
  }
  else // The node is strictly binary, so it will have two non-null children
  {
    char *l = TreeNode_toString(node->l); // l = left child
    char *r = TreeNode_toString(node->r); // r = right child
    sprintf(out, "(%s,%s):%.2f", l, r, node->distance);
  }

  return out;
}

3 个答案:

答案 0 :(得分:10)

您正在获取分段,因为out未初始化,而不是因为递归。你应该为它分配一些内存,例如

inline char *TreeNode_toString(const TreeNode *node)
{
  char *out = malloc(4096);  // <-- allocate

  ...

    char *l = TreeNode_toString(node->l);
    char *r = TreeNode_toString(node->r);
    snprintf(out, 4096, "(%s,%s):%.2f", l, r, node->distance);
    // ^-- please use snprintf to avoid buffer overflow, thanks.
    free(l);    // <-- remember to free
    free(r);    // <-- remember to free
  }

  return out;
}

答案 1 :(得分:6)

您没有为out分配任何内存,因此您正在写入随机内存位置。这个算法在这方面看起来有点不稳定 - 你怎么知道为out分配多少空间 - 你知道树上有一些大小的边界吗?

答案 2 :(得分:3)

发布的代码具有未定义的行为。抛开你的说法:

char * out;
sprintf(out, "%s:%.2f", node->name, node->distance);

换句话说,你试图输出一个未初始化的指针,这是未定义的行为,因此没有意义。

如果你问,我可以在递归函数中使用sprintf将信息添加到缓冲区,答案很可能,但不容易。您必须在每次递归调用时保持缓冲区,并且还必须为每个调用将更新的缓冲区索引。