简体   繁体   English

分段错误 - strcpy() - C.

[英]Segmentation Fault - strcpy() - C

I'm implementing a history feature for a command line shell. 我正在为命令行shell实现历史记录功能。 I've implemented a circular array to hold to ten most recent commands. 我已经实现了一个循环数组来保存十个最近的命令。 Each command is also labeled by an integer specifying which total command is. 每个命令也用整数标记,指定总命令是什么。 For Example, if 30 total commands were entered, the ten commands in the circular array would be numbered (30, 29, 28, 27,...,21). 例如,如果输入了30个命令,则圆形数组中的10个命令将被编号(30,29,28,27,...,21)。

If a user were to insert the command "r" followed by a number labeling one of the ten instructions then that instruction is supposed to run. 如果用户要插入命令“r”,后跟一个标记十条指令之一的数字,那么该指令应该运行。 I keep running into a seg fault when trying to ensure that a two word command is accepted properly. 在尝试确保正确接受双字命令时,我一直遇到段故障。 Can anyone help point out what the problem is. 任何人都可以帮助指出问题是什么。

int main(void)
{
    char inputBuffer[MAX_LINE]; /* buffer to hold the command entered */
    int background;             /* equals 1 if a command is followed by '&' */
    char *args[MAX_LINE/2+1];/* command line (of 80) has max of 40 arguments */

    int position, count, rnum = 0;
    char historyArray[10][MAX_LINE];
    char *holder[MAX_LINE]={0};

    while (1){            /* Program terminates normally inside setup */
        background = 0;
        printf("COMMAND->");
        fflush(0);

        setup(inputBuffer, args, &background);       /* get next command */

        position = (count % MOD_VAL);
        strcpy(historyArray[position],args[0]);

        if(!strcmp("rr",args[0]))
        {
            strcpy(historyArray[position],historyArray[((position-1)+MOD_VAL)%MOD_VAL]);
            printf("%i",count);
            printf("%c",'.');
            printf("%c",' ');
            printf("%s",historyArray[position]);
            printf("%c",'\n');
            strcpy(args[0],historyArray[position]);
        }

        else if(!strcmp("r",args[0])) //SEG FAULT OCCURING IN THIS ELSE-IF BLOCK!
        {
            //args[1] will hold given number
            printf("%c",'\n');
            printf("%s",args[0]);
            printf("%s",args[1]);
            printf("%s",args[2]);
            printf("%c",'\n'); //PRINT STATEMENTS FOR DEBUGGING

            strncpy(holder[0], args[2], MAX_LINE - 1); //SEG FAULT

            rnum = atoi(args[1]);
            strcpy(historyArray[position],historyArray[((position-(count-rnum))+MOD_VAL)%MOD_VAL]);
            strcpy(args[0],historyArray[position]); //CHANGES VALUES OF args[1], args[2]

            if(holder[0] != NULL)
            {
                strncpy(args[1],holder[0],MAX_LINE-1);
                args[2] = NULL;
            }
            else
            {
                args[1] = NULL;
            }

            printf("%c",'\n');
            printf("%s",args[0]);
            printf("%s",args[1]);
            printf("%s",args[2]);
            printf("%c",'\n');
        }

        else if(!(strcmp("h",args[0]))||!(strcmp("history",args[0])))
        {
            int counter = 0;
            while(counter < 10)
            {
                printf("%i",(count - counter));
                printf("%c",'.');
                printf("%c",' ');
                printf("%s", historyArray[((position - counter + MOD_VAL)%MOD_VAL)]);
                printf("%c",' ');
                printf("%c",'\n');
                counter ++;

                if(counter > count)
                    break;
            }
        }
        count++;

        pid_t pid1; //Initialize pid_t variable to hold process identifier
        pid1 = fork(); //Fork process and assign process identifier to "pid1"

        if (pid1 == 0) //Child process
        {
            //Child process executes the command specified by the user and
            //then quits.
            execvp(args[0], args);
            exit(0);
        }
        else //Parent process
        {
            if (background != 1)//Check for inclusion of '&' in command 
            {
                wait(NULL); //Wait for child process to finish executing
            }
        } 

        /* the steps are:
         (1) fork a child process using fork()
         (2) the child process will invoke execvp()
         (3) if background == 0, the parent will wait, 
         otherwise returns to the setup() function. */
    }
}

Any assistance is appreciated! 任何帮助表示赞赏!

-MATT -MATT

Here your args is the array of character pointers. 这里你的args是字符指针数组。

But strcpy requires two arguments - that should be array or character pointer to which memory allocated by malloc 但是strcpy需要两个参数 - 应该是character pointer to which memory allocated by malloc arraycharacter pointer to which memory allocated by malloc

But your strcpy(historyArray[position],args[0]); 但是你的strcpy(historyArray[position],args[0]); takes one argument as character pointer which will not be accepted. 将一个参数作为不接受的character pointer

so you can either change the args[] to args[][] or args[0] = malloc(some_no) , segfault will be removed. 这样你就可以改变args[]args[][]args[0] = malloc(some_no) segfault将被删除。

You note that the crash occurs on the line 您注意到崩溃发生在该行上

else if(!strcmp("r",args[0]))

If I were you, I would load the core file in a debugger and see what the value of args[0] is when passed to strcmp() . 如果我是你,我会在调试器中加载核心文件,看看传递给strcmp()args[0]的值是什么。

I expect you have compiler warnings about type mismatch between char and char* . 我希望你有关于charchar*之间类型不匹配的编译器警告。 You declare args as char* . 你将args声明为char* That means args[0] is a char , not a char* . 这意味着args[0]char ,而不是char* To compare the single character, just use a character instead of strcmp() : 要比较单个字符,只需使用一个字符而不是strcmp()

else if ('r' != args[0])

Some notes on pitfalls with C's string handling: 关于C字符串处理的陷阱的一些注意事项:

  • strcmp() isn't safe with respect to array boundaries when its arguments are not correctly NUL-terminated strcmp()在其参数未正确NUL终止时对于数组边界是不安全的
    • use strncmp() to provide a limit to the number of characters compared 使用strncmp()来提供对比的字符数限制
  • although strncpy() guards against array boundaries, it does not guarantee to NUL-terminate the destination string 虽然strncpy()防止数组边界,但它不能保证NUL终止目标字符串
  • strcpy() does not respect array boundaries; strcpy()不尊重数组边界; it is your responsibility to ensure the destination array is large enough to receive the string being copied to it 您有责任确保目标数组足够大以接收要复制到其中的字符串

You are missing to allocated memory the the char pointers held in args and holder . 你缺少分配内存的argsholderchar指针。

So referring to those as pointers to 0-terminated character arrays ("strings") via the str*() family of functions, leads to undefined bahaviour, as the str*() function try to derefernce those pointers not point to valid memory. 因此,通过str*()系列函数引用那些作为0终止字符数组(“字符串”)的指针,导致未定义的行为,因为str*()函数试图降低那些指向不指向有效内存的指针。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM