简体   繁体   English

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

[英]segmentation fault when trying to dereference a dynamically allocated pointer

I have a dynamically allocated char array, I want to combine two strings into it, so I tried the following: 我有一个动态分配的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;
}

When I ran it, it printed the size of nstr is 0 and then Segmentation fault (core dumped) . 当我运行它时,它打印的nstr大小为0,然后出现Segmentation fault (core dumped)

However when I did this: 但是,当我这样做时:

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;
}

It worked fine and printed the correct length of nstr . 它工作正常,并打印了正确长度的nstr I'm puzzled, what caused the crash? 我很困惑,是什么原因导致撞车?

You need to return the value of nstr that was originally returned by malloc() . 您需要返回malloc()最初返回的nstr值。

Your first code block increments nstr until it points to the end of the allocated memory. 您的第一个代码块递增nstr直到它指向分配的内存的末尾。 The code then attempts to use and free that address, which is not owned by your program. 然后,代码尝试使用并释放该地址,该地址不属于您的程序。

You need to save the starting address of the string so you can return it. 您需要保存字符串的起始地址,以便您可以返回它。

In your first case, you increment the nstr constantly, and in the end, you use 在第一种情况下,您不断增加nstr ,最后使用

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

where nstr points to the final location after all the increment (containing null ).Results in 0 length. 其中nstr指向所有增量之后的最终位置(包含null )。结果为0长度。 Then, you return the incremented pointer to the caller and try to free() it. 然后,将递增的指针返回给调用者,并尝试对其进行free() Results in Undefined Behavior . 导致未定义的行为

OTOH, in the second case, you have the pointer to the primarily allocated memory intact, through which you count the string length, returns correct value and later, free() -ing is also proper, so that works as expected. OTOH,在第二种情况下,您完整地指向了主要分配的内存的指针,通过该指针可以计算字符串长度,返回正确的值,然后free() ing也很合适,因此可以正常工作。

In the first function, you're returning the wrong pointer. 在第一个函数中,您将返回错误的指针。 It's pointing at the null terminator of the string, so the length is zero. 它指向字符串的空终止符,因此长度为零。 When you try to free() it, it isn't a pointer you got from malloc() . 当您尝试free()它时,它不是从malloc()获得的指针。 Undefined behavior results. 未定义的行为结果。

You're incrementing the nstr pointer when copying the two strings, and that's the pointer you're using to represent the string itself. 复制两个字符串时,您将增加nstr指针,这就是您用来表示字符串本身的指针。 Simply copy it in another variable and use it when referring to the string: 只需将其复制到另一个变量中,并在引用字符串时使用它:

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
}

You can see it in action here: https://ideone.com/ncpVMU 您可以在这里查看它的运行情况: https : //ideone.com/ncpVMU

I also took the liberty of fixing your goofy return statement: 我还随意修改了您的愚蠢的return语句:

return &(nstr[0]);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM