【问题标题】:Strtok() Segmentation faultStrtok() 分段错误
【发布时间】:2013-10-26 00:35:38
【问题描述】:
struct args
{
    char command[64];
    char args[2][64];
};

int argscount = 0;
struct args* arguments;
int buffersize = 64;
char *ptoken = NULL;
char input[buffersize];
char *pstr = NULL;



int a = read(0,input,buffersize);
pstr = input;
arguments = malloc(sizeof(struct args));        
if(a>0){  
    ptoken = strtok(&pstr," ");
    strcpy(arguments->command,ptoken);
    printf("TOKEN:%s\n", ptoken);
    while( ptoken != NULL ) {
        if(argscount > 1){break;}
        ptoken = strtok(NULL, ' ');
        strcpy(arguments->args[argscount],ptoken);
        argscount++;  
    }  
}

【问题讨论】:

    标签: c segmentation-fault strtok


    【解决方案1】:

    问题很可能出在

    ptoken = strtok(&pstr," ");
    

    strtok 的第一个参数应该是

    char *
    

    你有它

    char **
    

    【讨论】:

    • 好收获!我认为strtok 确实采用了char ** 并返回了新的指针以开始。我应该仔细检查一下。
    • OK,第一次尝试就可以了。但是对于那些在 while 循环中的人来说,它仍然无法正常工作。 ptoken = strtok(NULL, ' ') 看起来对吗?
    • 不要忽略警告 - 难怪你这样做会出错。 " " 是一个字符串,但 ' ' 是单个 char。注意你的编译器。提高您的警告级别,并解决所有问题。
    • 大家好,我修改了我的代码,但似乎 strtok() 不起作用。它没有用空格分割字符串。
    • 行“ptoken = strtok(NULL, ' ');”应该是“ptoken = strtok(ptoken,”“);”。此外,最好使用 gdb 单步执行您的代码并确保一切都符合预期。
    【解决方案2】:

    read 不会返回一个以空结尾的字符串,这是 strtok 所期望的。您需要在输入中分配一个额外的字节来添加'\0'。您可以查看read 的返回值以查看读取了多少字节,然后将'\0' 放置在input[a]

    int a = read(0,input,buffersize-1);
    input[a] = '\0';
    

    【讨论】:

    • 你看到你的TOKEN了吗:printf?您可以在调试器中单步调试或添加一些调试打印以查看崩溃发生的位置吗?
    • 其实..我改了之后,就变成了seg fault,什么都没有打印出来。
    • 我认为 Arun Taylor 解决了第二个难题。
    【解决方案3】:

    您的代码中的几个修复(和其他)。评论描述了我所做的更改:(如果定义了 read() 函数,它可能已经构建)还添加了 main,只是为了通过错误进行编译。

    #include <ansi_c.h>
    
     struct args
    {
        char command[64];
        char args[2][64];
    };
    
    int argscount = 0;
    struct args* arguments;
    size_t buffersize = 64; //changed to size_t
    char *ptoken = NULL;
    char input[64];  //variable initializer not allowed, changed
    char *pstr = NULL;
    
    int read(int a, char *s, size_t size);
    
    
    main(void)
    {
    
        int a = read(0,input,buffersize);
    
    pstr = input;
    arguments = malloc(sizeof(struct args));        
    if(a>0)
        {  
            ptoken = strtok(pstr," "); //changed &pstr to pstr
            strcpy(arguments->command,ptoken);
            printf("TOKEN:%s\n", ptoken);
            while( ptoken != NULL ) {
                if(argscount > 1){break;}
                ptoken = strtok(NULL, " "); //changed ' ' to " "
                strcpy(arguments->args[argscount],ptoken);
                argscount++;  
            }  
        }
    }
    

    【讨论】:

      【解决方案4】:

      这是一种正常、明智的做法:

      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      #include <unistd.h>
      
      struct args {
          char command[64];
          char args[2][64];
      };
      
      int main(void) {
          char input[64] = {0};
      
          if ( read(0, input, sizeof(input) - 1) == -1 ) {
              perror("unsuccessful read() operation");
              return EXIT_FAILURE;
          }
      
          char * ptoken = strtok(input, " ");
          if ( ptoken == NULL ) {
              fprintf(stderr, "No valid input\n");
              return EXIT_FAILURE;
          }
      
          struct args arguments;
          strcpy(arguments.command, ptoken);
          printf("COMMAND: %s\n", arguments.command);
      
          int argscount = 0;
          while ( ptoken && argscount < 2 ) {
              ptoken = strtok(NULL, " ");
              if ( ptoken ) {
                  strcpy(arguments.args[argscount], ptoken);
                  printf("TOKEN: %s\n", arguments.args[argscount++]);
              }
          }
      
          return 0;
      }
      

      输出:

      paul@local:~/src/c/scratch$ ./args
      test
      COMMAND: test
      
      paul@local:~/src/c/scratch$ ./args
      test this
      COMMAND: test
      TOKEN: this
      
      paul@local:~/src/c/scratch$ ./args
      test this one
      COMMAND: test
      TOKEN: this
      TOKEN: one
      
      paul@local:~/src/c/scratch$ ./args
      test this one two
      COMMAND: test
      TOKEN: this
      TOKEN: one
      paul@local:~/src/c/scratch$
      

      我会把去掉换行符作为练习留给你。

      【讨论】:

        猜你喜欢
        • 2012-02-15
        • 1970-01-01
        • 1970-01-01
        • 2023-03-24
        • 2023-04-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-08
        相关资源
        最近更新 更多