使用strcmp和char * arr []的分段错误

时间:2019-02-10 02:11:44

标签: c segmentation-fault strcmp

我正在创建一个外壳,并且我已经有一段时间没有使用C了。我已经正确初始化了外壳,但是当我尝试将用户输入与字符串数组进行比较时,却遇到了段错误。我计划在for循环中添加casce语句,以在用户调用每个进程后启动每个进程。由于我一直试图弄清楚如何使用户输入与字符串数组中的值匹配,所以我没有包括这些内容。在调试下,由于它是正确的指针,因此我仅接收该类生成的builtins [j]值的第一个字符。但是我被困住了,并且可以使用一些想法来解释为什么当我输入“ exit”时它没有返回0。谢谢

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>

//This code is for creating a basic shell
void init_shell(int num, char *prompt[]){
    char s1[] = "-p"; 
    int result;
    if(num>1){
    result = strcmp(s1, prompt[1]);
        if(result==0){
            printf("%s>$", prompt[2]);

        }else{
        printf("308sh>$");
        }
    }
    //printf("%s\n %s\n %s\n %d\n", prompt[0], prompt[1], prompt[2], result);
    else{
        printf("308sh>$");
    }

}

//用于接受用户输入直到关闭的无限循环

int main(int argc, char *argv[]){


    const char *builtins[7];    
    builtins[0] = "exit\n";
    builtins[1] = "pid\n";
    builtins[2] = "ppid\n";
    builtins[3] = "cd\n";
    builtins[4] = "pwd\n";
    builtins[5] = "set\n";
    builtins[6] = "get\n";

    char usr_in[]="";
    char cmp[]="";
    while(1==1){
        init_shell(argc, argv);//intial prompt for the shell
        fgets(usr_in,100,stdin); 

    //Check for builtin Commands

        int cmds_size = 7;
        int j=0;
        int res;

        for(j; j<cmds_size; j++){

            res=strcmp(usr_in, hold);
            if(res==0){

            printf("Execucting\n");
            }
            else{
                printf("no command\n");
            }
        }

    }

    return(0);
}

1 个答案:

答案 0 :(得分:0)

这里的问题是,您正在将用户的输入写入一个缓冲区,该缓冲区的大小不足以容纳空终止符以外的任何内容。

char user_in[] = "";

上面的行告诉C编译器您只需要足够的空间来存储[ '\0' ],它是一个字节。 C编译器不知道您以后可能会向该缓冲区写入100字节的字符串。

当写入缓冲区时,用户的输入溢出,并将覆盖堆栈中的其他值。由于堆栈中的其他值是指针,因此会发生段错误,因为您正在将字符值写入这些字节,但将它们解释为char指针。

您正在正确地将允许用户输入的大小限制为100个字符,但是您应确保缓冲区足够大以容纳要读取的值:

char user_in[101];
for(int i = 0; i < sizeof(user_in) / sizeof(user_in[0]); i++) {
  user_in[i] = 0; // Since this is allocated on the stack *in main*, this
                  // shouldn't be necessary
}

这里是如何重写主方法的一个示例:

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

typedef enum { false, true } bool; // If you don't have this
                                   // defined already

int main(int argc, char *argv[]) {

  const char *builtins[7];    
  builtins[0] = "exit\n";
  builtins[1] = "pid\n";
  builtins[2] = "ppid\n";
  builtins[3] = "cd\n";
  builtins[4] = "pwd\n";
  builtins[5] = "set\n";
  builtins[6] = "get\n";

  char user_in[101];
  for(int i = 0; i < sizeof(user_in) / sizeof(user_in[0]); i++) {
    user_in[i] = 0;
  }

  while(1) {
    printf("Enter a command: ");
    fgets(user_in, 100, stdin);

    bool found = false;
    for(int i = 0; i < sizeof(builtins) / sizeof(builtins[0]); i++) {
      if (!strcmp(user_in, builtins[i])) {
        printf("Found command %s", builtins[i]);
        found = true;
        break;
      }
    }

    if (!found) {
      printf("Didn't find command\n");
    }
  }

  return 0;
}

此外,关于函数init_shell:您正在检查argc是否大于1,但这仅保证定义了argv[1];它不能保证定义了argv[2]。 (请记住,argc是argv数组的大小,其中第一个元素是正在执行的程序的名称)。您要确保在以自己的方式检查提示标志之前,argc至少为3。

对于您的用例而言,这可能是过高的选择,但是请考虑使用getopt函数从用户那里获取自定义提示值。有关该方法的文档,请参见http://man7.org/linux/man-pages/man3/getopt.3.html