【问题标题】:Function that returns string is not working- segmentation fault返回字符串的函数不起作用 - 分段错误
【发布时间】:2013-11-15 03:41:45
【问题描述】:

我有一个非常简单的函数给我带来了一些问题。我要做的就是在从字符串更改子字符串后返回一个子字符串。但是当我运行代码时,我遇到了分段错误。我的代码发生了什么:

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

const char *new_name(char str[])
{

  char * pch;
  char * last="";
  char * pch2;
  static char name[80];
  printf ("Splitting string \"%s\" into tokens:\n",str);

  pch = strtok (str,"/");
  while (pch != NULL)
  {
     last=pch;
     pch = strtok (NULL, "/");

  }

  pch2 = strtok (last,".");
  strcpy(name, pch2);
  strcat(name, ".ppm");

  return name; 
}

int main()
{
  printf("New name: %s",new_name("/home/test/segmentation/test.pgm"));
  return 0;

}

编辑:我还有一个问题:我想使用这个函数的返回作为另一个函数的输入,但它接受 char 并且返回的值是 const char。如何进行转换?

【问题讨论】:

  • 在这里使用 strtok 似乎有点过头了,使用一个简单的循环来查找最后一个 / 通过从末尾循环 char* ch; for (ch = str + strlen(str) - 1; ch != '/'; --ch); 现在 ch 指向 '/',您现在还可以将任何内容传递给函数,因为您没有修改参数。

标签: c string segmentation-fault strtok


【解决方案1】:

崩溃发生在 strtok 中。问题是您将指向字符串文字的指针作为其第一个参数传递,而字符串文字通常位于只读内存中,因此 strtok 在尝试更改字符串时会崩溃。

char *strtok(char *str, const char *delim);

一种解决方法:

char fileName[] = "/home/test/segmentation/test.pgm";
printf("New name: %s",new_name(fileName));

编辑:在“编辑”下方回答您的问题。

只需更改函数的签名以返回char *

char *new_name(char str[])

不过,再多修改一下就好了。与其使用本地静态缓冲区 (name),不如将缓冲区作为第二个参数传递,并在调用函数之前在客户端代码中分配它。这种方法的问题是调用者通常不知道要生成的字符串的确切长度甚至最大长度。

另一个可能更好的选择是分配缓冲区的内存以使用malloc 动态返回并将指向它的指针返回给调用者。在这种情况下,释放缓冲区的责任将由用户代码负责,因此您应该正确记录它。

【讨论】:

  • @mad 不是真的。这是什么?
  • 我想将函数的返回值用作 char 以便它可以作为另一个函数的输入。怎么办?
【解决方案2】:

strtok 的第一个参数不能是常量字符串(这就是字符串字面量):

pch = strtok (str,"/");
              ^^^

因为它修改了它的第一个参数,链接文档说:

char *strtok( char *restrict str, const char *restrict delim );

这个函数是破坏性的:它在字符串str的元素中写入'\0'字符。特别是,字符串文字不能用作 strtok 的第一个参数。

使用非常量数组可以解决这个问题:

char arr[]  = "/home/test/segmentation/test.pgm" ;
printf("New name: %s",newname(arr));

为了完整起见,修改 字符串文字undefined behavior 部分 C99 标准草案 6.4.5 字符串文字 段落 6 说(强调我的):

如果这些数组的元素具有 适当的值。 如果程序试图修改这样的数组,行为是 未定义

【讨论】:

  • @glglgl 我明白it's 的意思,这是一个错字。
【解决方案3】:

strtok 将修改它的第一个参数,因此您不能将指向字符串文字的指针传递给它,这会调用未定义的行为。

main的前两行改成这样:

char str[] = "/home/test/segmentation/test.pgm";
printf("New name: %s\n",new_name(str));

【讨论】:

    【解决方案4】:

    new_name("/home/test/segmentation/test.pgm")

    您正在传递一个字符串文字(只读),而strtok 正在修改此字符串

    【讨论】:

      【解决方案5】:

      strtok 通过改变它传递的字符串来工作。您不能将常量字符串传递给strtok

      你可以试试

      char str[] = "/home/test/segmentation/test.pgm";
      printf("New name: %s",new_name(str));
      

      改为。

      【讨论】:

        【解决方案6】:

        您必须记住strtok 函数修改字符串输入。然后将指针传递给 constant (即只读)的文字字符串。尝试修改文字字符串会导致未定义的行为。

        解决方法很简单:

        char str[] = "...";
        printf("New name: %s\n", new_name(str));
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-03-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-06-06
          • 1970-01-01
          • 1970-01-01
          • 2017-04-15
          相关资源
          最近更新 更多