【问题标题】:segmentation fault when trying to dereference a dynamically allocated pointer尝试取消引用动态分配的指针时出现分段错误
【发布时间】:2015-11-10 20:39:06
【问题描述】:

我有一个动态分配的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 长度。我很疑惑,是什么导致了崩溃?

【问题讨论】:

  • 你应该使用 gdb 来调试 file.core,看看到底哪里出了问题。
  • x[0]*x 含义相同

标签: c pointers char


【解决方案1】:

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

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

你需要保存字符串的起始地址以便返回它。

【讨论】:

  • 不,&* 完全没用,它会自行取消。
  • @razzak: &(nstr[0]) 返回与nstr 相同的结果。此时,nstr[0] 引用了字符串中的最后一个字符,因为nstr 的值发生了变化。
  • @JonathanWood 感谢您澄清这一点,我很困惑,因为我看到它被用来获取像char arr[20] = "whatever"; char *ptr = &(char[0]) 这样的数组指针的实例,所以我认为它总是会返回一个指向开头的指针数组。
【解决方案2】:

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

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

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

OTOH,在第二种情况下,您拥有完整的指向主要分配内存的指针,通过它您可以计算字符串长度,返回正确的值,然后free()-ing 也是正确的,因此可以按预期工作。

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      您在复制两个字符串时增加了nstr 指针,这就是您用来表示字符串本身的指针。只需将其复制到另一个变量中并在引用字符串时使用它:

      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
      }
      

      你可以在这里看到它的实际效果:https://ideone.com/ncpVMU

      我还冒昧地修复了您愚蠢的退货声明:

      return &(nstr[0]);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-24
        • 1970-01-01
        • 2022-11-16
        • 1970-01-01
        • 2020-02-18
        • 2016-02-23
        • 2020-03-20
        • 1970-01-01
        相关资源
        最近更新 更多