Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
strcat上的段故障_C_Segmentation Fault - Fatal编程技术网

strcat上的段故障

strcat上的段故障,c,segmentation-fault,C,Segmentation Fault,我的代码有段错误,但我真的不知道原因 char *cord_tostring(cord_t R) { if (R == NULL) return NULL; char *str = malloc(sizeof(char) * 10000); if (R->left == NULL && R->right == NULL) return R->data; strcat(str, cord_tostri

我的代码有段错误,但我真的不知道原因

char *cord_tostring(cord_t R) {
    if (R == NULL)
        return NULL;
    char *str = malloc(sizeof(char) * 10000);
    if (R->left == NULL && R->right == NULL)
        return R->data;
    strcat(str, cord_tostring(R->left));
    strcat(str, cord_tostring(R->right));
    return str;
}
在哪里

typedef struct cord_node *cord_t;
typedef struct cord_node cord;
struct cord_node {
    int len;
    cord *left;
    cord *right;
    char *data;
};

strcat
需要以NUL结尾的字符串

函数的作用是:将 s2(包括终止的NUL字符)到字符串的结尾 由s1指向s2的初始字节覆盖NUL s1结尾的字符。如果在对象之间进行复制 如果重叠,则行为未定义

改为

char *str = malloc(10000);
str[0] = '\0';
或者更好(正如@EugeneSh在评论中指出的)使用strcpy,它不需要NUL终止符

strcpy(str,cord_tostring(R->left));
strcat(str,cord_tostring(R->right));

您的代码中存在许多问题:

  • 您不检查
    malloc()
    是否成功。在许多系统上,
    malloc()
    可能会失败并返回
    NULL
    。应该测试和报告此类故障,而不是调用未定义的行为

  • malloc()
    分配的块未初始化:将其作为目标调用
    strcat()
    具有未定义的行为。您应该将其第一个字节初始化为
    '\0'
    或使用
    strcpy()
    而不是
    strcat()

  • 在递归之前,测试
    R->left
    R->right
    是否都是
    NULL
    ,但如果只有一个
    NULL
    ,则将使用
    NULL`源指针调用
    strcat()

  • 您没有释放为每个节点分配的指针,导致大量内存泄漏,最终导致内存分配失败或更糟

  • 将所有
    数据
    字段连接在一起,不使用任何分隔符。这可能是预期的行为,也可能不是,这取决于你的目标

以下是更正的版本,使用空格作为分隔符:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *cord_tostring(cord_t R) {
    if (R == NULL)
        return NULL;
    if (R->left == NULL && R->right == NULL)
        return R->data ? strdup(R->data) : NULL;

    char *s1 = cord_tostring(R->left);
    char *s2 = cord_tostring(R->right);
    if (s1 == NULL)
        return s2;
    if (s2 == NULL)
        return s1;

    char *s = malloc(strlen(s1) + 1 + strlen(s2) + 1);
    if (s == NULL) {
        fprintf(stderr, "Memory allocation failure\n");
        exit(1);
    }
    sprintf(s, "%s %s", s1, s2);
    free(s1);
    free(s2);
    return s;
}
#包括
#包括
#包括
字符*跳线到串(跳线R){
if(R==NULL)
返回NULL;
如果(R->left==NULL&&R->right==NULL)
返回R->data?strdup(R->data):空;
char*s1=跳线(右->左);
char*s2=跳线(R->右侧);
如果(s1==NULL)
返回s2;
if(s2==NULL)
返回s1;
char*s=malloc(strlen(s1)+1+strlen(s2)+1);
如果(s==NULL){
fprintf(stderr,“内存分配失败”);
出口(1);
}
sprintf(s,“%s%s”,s1,s2);
免费(s1);
免费(s2);
返回s;
}

请注意,
cord\u to\u string()
的返回值应在使用后释放。

您的树有多大?请尝试
*str=0
在strcat
@Zakir之前,或者使用
calloc()
,这将返回一个设置为零的数组。@Zakir将分配后的所有字节都memset为0(NULL)并不总是一个好主意。不,它只是不是。@Zakir:如果您想将所有位完全初始化为零,请使用
calloc()
。使用
memset()。。。。并在每次递归调用后添加
free
str[0]='\0'
可以是
str[0]=0
@i486:这两个语句是等效的,但第一个语句更可取,因为它传递了额外的信息
NULL
0
在许多情况下也是等效的,但是使用
NULL
是对NULL指针更明确的拼写。@chqrlie
NULL
可能与0不同。但是
'\0'
始终是
0
,并且没有额外的信息-只有额外的字符和更差的可读性。@i486:额外的字符不一定会降低可读性:运算符周围的额外空格和适当的缩进实际上提高了可读性。在这种情况下,
0
还是
'\0'
更具可读性,取决于品味和当地习俗。我个人喜欢后者,但你显然不同。没关系。更重要的是一致性。简化的另一种情况是
sizeof(char)*10000
,根据定义,除了类型之外,它与
10000
相同。@OzgurMurat:returning
是一个问题:应该始终分配返回值,或者调用方无法确定是否释放它。最好测试
NULL