【问题标题】:Segmentation Fault in C function [closed]C函数中的分段错误[关闭]
【发布时间】:2013-04-09 05:44:08
【问题描述】:

我正在尝试开发一个基本的外壳。对于那个 shell,我需要一个 C 函数来解析一个字符串。由于我是 C 新手,我尝试开发一个基本功能,但它给了我一个分段错误错误。请告诉我我错过了什么。

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


void parse(char *msg);
int main()
{
    char *msg =  "This is a message";
    parse(msg);
}

void parse(char *msg){
    char *mm;
    mm = msg;

    char *tok;
    tok = strtok(mm," ");
    while(tok == NULL){
        tok = strtok(NULL," ");
            printf("%s \n",tok);
    }
}

错误消息(运行时)

Segmentation fault (core dumped)

提前致谢

【问题讨论】:

  • 你们会问多少次同样的问题而不是 RTFM?字符串字面量是常量,没有办法你可以修改它们的内容。
  • (出于完全相同的原因,const char *msg = "foo";
  • @H2CO3,也许是时候编辑 C 标记 wiki 类似问题以添加与 undefined behavioursockets 相关的问题,因为它们似乎被问得太多了?
  • @AnishRam 这是一个建设性的建议。 (不幸的是,提出这类问题的人也不倾向于阅读标签维基。)
  • @H2CO3,嗯。好点子。 (开始集思广益新功能请求:D)

标签: c segmentation-fault


【解决方案1】:

msg 指向一个字符串文字,并且您正在尝试修改它。在 C 中,修改字符串字面量是 undefined behaviour(实际上,编译器通常将它们放在只读内存中)。

要修复,请将msg 转换为数组:

int main()
{
    char msg[] =  "This is a message";
    parse(msg);
}

此外,您的 while 循环也存在一些问题:

1) 条件错误;
2) 第二个strtok() 调用应该出现在printf() 之后

void parse(char *msg){
    char *mm = msg;
    char *tok = strtok(mm, " ");
    while (tok) {
        printf("%s \n",tok);
        tok = strtok(NULL," ");
    }
}

【讨论】:

  • @phresnel 修改它们会导致 UB 的事实允许编译器将它们放置在 ROM 中。原来的措辞也很好。
  • @H2CO3:这正是我原来的措辞的意思,谢谢。我已经更改了它,因为它似乎不够清楚。
  • @H2CO3:或者可以说,至少对一个人来说,这个措辞并不是完全明确的(“从什么开始的”)。我删除了我的评论。 +1 顺便说一句。
  • @phresnel 我明白了,谢谢。
【解决方案2】:

您不能可靠地修改字符串文字;它们通常是只读的(在您的情况下,显然是只读的)。尝试修改字符串文字会调用未定义的行为,这始终是一件坏事™!

用途:

int main(void)
{
    char msg[] = "This is a message";
    parse(msg);
}

【讨论】:

  • 你是怎么写商标符号的?我可以写上标或下标吗?我知道它的题外话,但很好奇。
  • @Koushik 你总是可以从 Wikipedia 这样的地方复制角色。此外,对于有关 Stack Overflow 的格式化等问题,还有meta.stackoverflow.com
  • @Koushik:在 Mac 键盘上,选项 2。或者使用键盘查看器或字符查看器。在其他地方,通常有一种方法,但并不总是显而易见的。 Unicode 码位是 U+2122;你也许可以用 Alt 键做一些事情,然后......最终输入 2122。
  • 请注意,您也可以使用一些允许的 HTML 来“伪造”TM-thingy。编辑:显然,在 cmets 中它不起作用。
  • 有人想提出问题吗?如何在 Windows 或 Linux 或 Mac 键盘上输入任意 Unicode 字符?
【解决方案3】:

你的定义:

char *msg =  "This is a message";

使msg 成为无法修改的常量字符字符串。但是strtok 修改了它。

你可能想把它改成

char *msg =  strdup("This is a message");

完成后别忘了释放指针。

【讨论】:

    【解决方案4】:

    也许不是

    while(tok == NULL)
    

    你是说

    while(tok != NULL)
    

    或者只是

    while (tok) // <- because in C, conditions are always compared to 0
    

    。但是,给您带来分段错误的是strtok 修改了传递的字符串,这就是为什么它需要一个指向char非const 指针(请参阅http://linux.die.net/man/3/strtok)。因此,因为您传递了一个指向不可修改的字符串文字的指针,所以您会收到分段错误(这是您的 luck;如果您运气不好,这个错误也可能会通过 QA 并投入生产)。

    【讨论】:

      【解决方案5】:

      去吧…………

      #include<string.h>
      #include<stdio.h>
      
      
      void parse(char *msg);
      int main()
      {
          char msg[] =  "This is a message";
          parse(msg);
      }
      
      void parse(char *msg){
          char *mm;
          mm = msg;
      
          char *tok;
          tok = strtok(mm," ");
          while(tok != NULL){
              printf("%s \n",tok);
          tok = strtok(NULL," ");
          }
      }
      

      【讨论】:

      • 抱歉,这根本没有帮助。我的建议是不要发布“试试这个”答案(另请参阅我的个人资料页面)。
      • 您的编辑不会让这更有帮助。添加一些解释如何?
      • 我没有得到你想要的关于这个的澄清?
      • 你给了提问者一个完整的解决方案。这现在可能有效。但提问者可能不会从中学到任何东西。有句话说:“授人以鱼,养人一日;授人以渔,养人终生。”
      • 感谢您的建议.....真的很有帮助
      【解决方案6】:

      如何将 tok==NULL 改为 tok!=NULL

      【讨论】:

      • 但是当你发布这个答案时已经是多余的了,这就是为什么 Stack Overflow 在按下提交按钮时会通知你新的答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-17
      • 1970-01-01
      相关资源
      最近更新 更多