将指向char数组的指针传递给函数

时间:2017-06-30 16:45:17

标签: c segmentation-fault

这条代码工作正常,直到我修改它。

int main(int argc, char** argv)
{
    char command[1024];
    gets(command);
    char *delim = " \t\f";
    char **tokens;
    int i=0;
    /* Extracting tokens from command string */
    for(tokens[i] = strtok(command, delim); tokens[i] != NULL; tokens[i] = strtok(NULL, delim))
    {
       i++;
    }
    return 0;
}

这是在网上遇到Segmentation Fault崩溃的代码 for(tokens[i] = strtok(command, delim); tokens[i] != NULL; tokens[i] = strtok(NULL, delim))

代码

void commandProcess(char command[])
{
    char *delim = " \t\f";
    char **tokens;
    int i=0;
    /* Extracting tokens from command string */
    for(tokens[i] = strtok(command, delim); tokens[i] != NULL; tokens[i] = strtok(NULL, delim))
    {
       i++;
    }
}

int main(int argc, char** argv)
{
    char command[1024];
    gets(command);
    process(command);
    return 0;
}

我知道char command[]衰减到指针link,并且strtok()修改了它的第一个参数,在我的情况下,它可能是一个未定义的行为。 link

那么,有人可以请我提供其他方法,以便我可以使用相同的功能签名来解决问题吗?

这似乎是一个微不足道的问题,但我无法通过它。 :\我甚至试过这个,

void commandProcess(char command1[])
{
    char command[1024];
    int length = strlen(command1);
    strncat(command, command1, length);
    command[length] = '\0';

    char *delim = " \t\f";
    char **tokens;
    int i=0;

    /* Extracting tokens from command string */
    for(tokens[i] = strtok(temp_command, delim); tokens[i] != NULL; tokens[i] = strtok(NULL, delim))
    {
       i++;
    }

然后再次在线上崩溃

for(tokens[i] = strtok(temp_command, delim); tokens[i] != NULL; tokens[i] = strtok(NULL, delim))

我认为delim& tokens不是罪魁祸首,因为没有commandProcess()的程序可以正常使用它们。

2 个答案:

答案 0 :(得分:1)

您写信至tokens[i],但tokens从未初始化。取消引用未初始化的指针会调用undefined behavior

这意味着代码的行为是不可预测的。它可能会崩溃,它可能会显示奇怪的结果,或者它似乎可以正常工作。此外,进行看似无关的代码更改可以更改未定义的行为的显示方式。这就是你的情况。

要解决此问题,您需要为tokens分配空间。在这种情况下,最简单的方法是制作一个固定大小的指针数组:

char *tokens[1024];

您还可以malloc内存,这样您就不会在堆栈上放置大型数组:

char **tokens = malloc(sizeof(char *) * 1024);

由于command的长度为1024,因此令牌的数量不应该更大。

答案 1 :(得分:1)

正如其他评论和答案所指出的那样,您需要为收集的令牌指针分配空间。

这是一个固定版本,它也使用fgets()而不是过时且危险的gets()。通常,不幸的是,fgets有点令人讨厌,因为它会在缓冲区中留下尾随\n。但是,在这里,我们可以简单地将'\n'添加到delim变量中,告诉strtok要拆分的内容。

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

#define MAXTOKS 100

void commandProcess(char command[])
{
    char *delim = " \t\f\r\n";
    char *tokens[MAXTOKS+1];
    int i=0;
    /* Extracting tokens from command string */
    for(tokens[i] = strtok(command, delim); tokens[i] != NULL; tokens[i] = strtok(NULL, delim))
    {
       i++;
       if(i > MAXTOKS)
       {
          fprintf(stderr, "too many tokens\n");
          exit(1);   
       }
    }
    for(i = 0; tokens[i] != NULL; i++) printf("%d: \"%s\"\n", i, tokens[i]);
}

int main(int argc, char** argv)
{
    char command[1024];
    fgets(command, sizeof(command), stdin);
    commandProcess(command);
    return 0;
}