简体   繁体   English

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

[英]Segmentation fault using strcmp and char *arr[]

I am working on creating a shell and I haven't use C for a while. 我正在创建一个外壳,并且我已经有一段时间没有使用C了。 I have the shell initizing properly but when I try to compare the user input to an array of strings I have I get a segmentation fault. 我已经正确初始化了外壳,但是当我尝试将用户输入与字符串数组进行比较时,却遇到了段错误。 I was planning on adding casce statements in a the for loop to initiate each of the processes once they are called by the user. 我计划在for循环中添加casce语句,以在用户调用每个进程后启动每个进程。 I haven't included those since I have been trying to figure out how to get the user input to match with a value in my string array. 由于我一直试图弄清楚如何使用户输入与字符串数组中的值匹配,所以我没有包括这些内容。 Under debug I was only receiving the first character of the builtins[j] value which kind of makes since since it is a pointer right. 在调试下,由于它是正确的指针,因此我仅接收该类生成的builtins [j]值的第一个字符。 However I am stuck and could use some ideas for why this isn't returning 0 when I input "exit". 但是我被困住了,并且可以使用一些想法来解释为什么当我输入“ exit”时它没有返回0。 Thanks 谢谢

#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>$");
    }

}

//The infinite loop for accepting user input until it closes //无限用户接受直到关闭的输入

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);
}

The issue here is that you're writing the user's input to a buffer that isn't big enough to hold anything other than a null terminator. 这里的问题是,您正在将用户输入写入缓冲区,该缓冲区的大小不足以容纳空终止符以外的任何内容。

char user_in[] = "";

The above line tells the C compiler that you need just enough space to store [ '\\0' ] , which is a single byte. 上一行告诉C编译器,您只需要足够的空间来存储[ '\\0' ] (这是一个字节)。 The C compiler doesn't know that you may later write a 100-byte string to that buffer. C编译器不知道您以后可能会向该缓冲区写入100字节的字符串。

When you write to the buffer, the user's input overflows and will overwrite other values in your stack. 当您写入缓冲区时,用户的输入将溢出,并将覆盖堆栈中的其他值。 Since the other values in your stack are pointers, what'll happen is you'll run into seg-faults, since you're writing character values into those bytes, but interpreting them as char pointers. 由于堆栈中的其他值是指针,因此会发生段错误,因为您正在将字符值写入这些字节,但是将它们解释为char指针。

You are correctly limiting the size of the allowed input from the user to 100 characters, but you should make sure that your buffer is big enough to hold the value you're reading in: 您正在正确地将允许用户输入的大小限制为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
}

Here's one example of how you can rewrite your main method: 这是一个如何重写主方法的示例:

#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;
}

Also, regarding your function init_shell : you're checking to see if argc is greater than 1, but that only guarantees that argv[1] is defined; 另外,关于您的函数init_shell :您正在检查argc是否大于1,但这仅保证定义了argv[1] it doesn't guarantee that argv[2] is defined. 它不能保证定义了argv[2] (Remember, argc is the size of the argv array, where the first element is the name of the program being executed). (请记住,argc是argv数组的大小,其中第一个元素是正在执行的程序的名称)。 You want to make sure that argc is at least 3 before checking for the prompt flag in the way you are. 您要确保在以自己的方式检查提示标志之前,argc至少为3。

It may be overkill for your use-case, but consider using the getopt function for getting a custom prompt value from the user. 对于您的用例来说,这可能是过高的选择,但是请考虑使用getopt函数从用户那里获取自定义提示值。 See http://man7.org/linux/man-pages/man3/getopt.3.html for documentation regarding that method. 有关该方法的文档,请参见http://man7.org/linux/man-pages/man3/getopt.3.html

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

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