尝试取消引用动态分配的指针时出现分段错误

时间:2015-11-10 20:39:06

标签: c pointers char

我有一个动态分配的char数组,我想将两个字符串合并到其中,所以我尝试了以下内容:

char *strcpy2 (char *str1, char *str2)
{
    int total = strlen (str1) + strlen (str2) + 1;
    char *nstr = malloc (sizeof (char) * total);
    while (*str1 != '\0') *nstr++ = *str1++;
    while (*str2 != '\0') *nstr++ = *str2++;
    *nstr = '\0';
    printf ("size: %d\n", strlen (nstr));
    return &(nstr[0]);
}

int main (void)
{
    char *concat = strcpy2 ("Hello, ", "World.");
    puts (concat);
    free (concat);
    return 0;
}

当我运行它时,打印的nstr的大小为0,然后是Segmentation fault (core dumped)

然而,当我这样做时:

char *strcpy2 (char *str1, char *str2)
{
    int total = strlen (str1) + strlen (str2) + 1;
    char *nstr = malloc (sizeof (char) * total);
    char *p = nstr;
    while (*str1 != '\0') *p++ = *str1++;
    while (*str2 != '\0') *p++ = *str2++;
    *p = 0;
    printf ("size: %d\n", strlen (nstr));
    return nstr;
}

工作正常并打印了nstr的正确长度。我很困惑,是什么导致了撞车?

4 个答案:

答案 0 :(得分:4)

您需要返回nstr最初返回的malloc()的值。

您的第一个代码块递增nstr,直到它指向已分配内存的末尾。然后代码尝试使用并释放该地址,该地址不属于您的程序。

您需要保存字符串的起始地址,以便将其返回。

答案 1 :(得分:1)

在第一种情况下,您不断增加nstr,最后使用

printf ("size: %d\n", strlen (nstr));

其中nstr指向所有增量(包含null)后的最终位置。结果为0长度。然后,将递增的指针返回给调用者并尝试free()它。结果在Undefined Behavior

OTOH,在第二种情况下,你有一个指向主要分配的内存的指针,你通过它来计算字符串长度,返回正确的值,之后,free() - ing也是正确的,所以它起作用预期

答案 2 :(得分:0)

在第一个函数中,您返回错误的指针。它指向字符串的null终止符,因此长度为零。当您尝试free()它时,它不是您从malloc()获得的指针。未定义的行为结果。

答案 3 :(得分:0)

复制两个字符串时,您正在递增The sample code can be seen in this fiddle:指针,这是您用来表示字符串本身的指针。只需将其复制到另一个变量中,并在引用字符串时使用它:

nstr

您可以在此处看到它:https://ideone.com/ncpVMU

我也冒昧地修复了你的愚蠢归还声明:

char *strcpy2 (char *str1, char *str2)
{
    int total = strlen (str1) + strlen (str2) + 1;
    char *nstr = malloc (sizeof (char) * total);
    char *str = nstr;                                // the string
    while (*str1 != '\0') *nstr++ = *str1++;
    while (*str2 != '\0') *nstr++ = *str2++;
    *nstr = '\0';
    printf ("size: %d\n", strlen (str));             // used here
    return str;                                      // and here
}