C segfault在递归函数中调用strcat

时间:2014-03-20 22:41:49

标签: c recursion segmentation-fault strcat

在尝试使用c中的strcat连接到字符串时,我遇到了段错误。 gdb中的错误是:

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 1 (LWP 1)]
0xff1692b4 in strcat () from /lib/libc.so.1

相关代码如下。我在调用函数中对传入的char * returnedString进行malloc,传递给returnedString的初始值只是“”。

char * printPostOrder(struct block * node, char * returnedString)
 {
 char * temp;
   temp = (char *)malloc(50 * sizeof(char));
  temp[0]='\0';
if(temp){
if (node != NULL)
{
    returnedString = printPostOrder(node -> left,returnedString);
    returnedString = printPostOrder(node -> right,returnedString);

    if (node -> left == NULL || node -> right == NULL)
    {
        if (node -> flag == 1)
        {
            sprintf(temp,"(%dA)\0",node -> size);
            strcat(returnedString,temp);
            free(temp);
        }
        else
        {
            sprintf(temp,"(%dF)\0",node -> size);
            //printf("%c",temp);
            strcat(returnedString,temp);

        }

    }
free(temp);
}
}

return returnedString;

}

真的很感激任何帮助!

3 个答案:

答案 0 :(得分:2)

首先,这两行

char * temp;
temp = (char *)malloc(50 * sizeof(char));

应替换为此行

char temp[50];

否则,每次调用该函数时都会泄漏50个字节的内存。

其次,在顶层,returnedString应声明为

static char returnedString[1000000];

因为你几乎肯定会超越你strcat进入的缓冲区。

作为解释,strcat的文档说,"字符串s1必须有足够的空间来保存结果。"请注意s1strcat的第一个参数,即输出缓冲区。 strcat无法为您管理内存,并且不会使输出缓冲区变大。如果输出缓冲区不够大,它就会崩溃。因此,您需要确保以大输出缓冲区开始。您可以malloc缓冲,或者只是静态地声明它,如上所示,但您需要确保它足够大才能保留最终结果。

答案 1 :(得分:0)

首先,您并未在任何地方致电free(temp)

最好的情况是,这只会占用大量内存,但不会造成任何问题。

最糟糕的情况是(取决于您正在遍历的树的大小以及可用的内存量),实际上您的内存不足。由于您未检查malloc()是否返回NULL,因此您会将NULL指针传递给sprintf(),这很可能是您的原因所在段错误。

答案 2 :(得分:0)

假设您为“返回的字符串”分配了足够的内存,我建议这样:

    char * printPostOrder(struct block * node, char * returnedString)
    {
            if (node != NULL)
            {
                    returnedString = printPostOrder(node -> left,returnedString);
                    returnedString = printPostOrder(node -> right,returnedString);

                    if (node -> left == NULL || node -> right == NULL)
                    {
                            if (node -> flag == 1)
                            {
                                    returnedString += sprintf(returnedString, "(%dA)",node -> size);
                            }
                            else
                            {
                                    returnedString += sprintf(returnedString, "(%dF)",node -> size);
                            }
                    }
            }
            return returnedString;
    }

snprintf返回写入的字符数,因此这样您就可以始终将此指针指向字符串的结尾。每次你在那里写,你有效地追加到原始字符串的末尾。 仍然,“假设你为返回的字符串分配了足够的内存”很重要。

关于strcat(str0,str1)的注释:它不知道str0在哪里结束,因此每次调用它时,它都会遍历str0中的字符以找到结束。只是更新一个指向字符串当前末尾的指针对我来说似乎比重新计算长度更好。