views:

170

answers:

3

In C, is it possible to use recursion within the sprintf function ? For some reason I get a segmentation fault when I do it:

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;
}
+10  A: 

You're getting segment because out is not initialized, not because of the recursion. You should allocate some memory for it, e.g.

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;
}
KennyTM
You mean allocated not initialized - the stating value of out does not matter just some memory space
Mark
+6  A: 

You didn't allocate any memory for out, so you're writing into a random memory location. This algorithm seems a bit shaky on that front - how will you know how much space to allocate for out - do you know some size bounds on the tree?

Carl Norum
ohh... Thanks for the answer. Well... I understand the problem (I thought sprintf took care of allocating the memory)... But I don't know how to solve it. In Java it was simplypublic String toString() { if(isExternal()) return name + ":" + distance; else return "(" + l.toString() + ":" + r.toString + ")";}
Shinka
+3  A: 

The code as posted has undefined behaviour. recursion aside you are saying:

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

In other words you are trying to output to an uninitialised pointer, which is undefined behaviour, and thus is meaningless.

If you are asking, can I use sprintf in a recursive function to add information to a buffer, the answer is possibly, but not easily. You would have to maintain a buffer outwith each recursive call and also an index to the buffer that each call would update.

anon