C-接收我的Minishell计划的SEG故障



我正在编写一个迷你壳程序。它为我提供了" args = my_str2Vect(line)"的行中的seg故障。" my_str2vect"函数虽然工作正常,以及my_strncpy函数和my_strlen函数(返回char数组的长度)。那么那条线怎么了?

#define _POSIX_SOURCE
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>  
#include <signal.h>
#include "../../include/my.h"


pid_t pid;
int childrunning = 0;
void minishell_loop();
/*
  Your shell must also support CTRL+C by using UNIX signals. 
  If you type CTRL+C your prompt must not exit 
  and instead kill the currently running process (or do nothing if there is none).
*/
void int_handler(int sig){
  if(childrunning == 1){
    kill(pid, SIGUSR2);
  }else{
    my_str("n");
    minishell_loop();
  }
}
void killkillkill(int sig){
    exit(0);
}
/*
  Function Declarations for builtin shell commands:
 */
int minishell_cd(char **args);
int minishell_help(char **args);
int minishell_exit(char **args);
/*
  List of builtin commands, followed by their corresponding functions.
 */
char *builtin_str[] = {
  "cd",
  "help",
  "exit"
};
int (*builtin_func[]) (char **) = {
  &minishell_cd,
  &minishell_help,
  &minishell_exit
};
int minishell_mum_bultins() {
  return sizeof(builtin_str) / sizeof(char *);
}
/*
  Builtin function implementations.
*/
/**
   @brief Bultin command: change directory.
   @param args List of args.  args[0] is "cd".  args[1] is the directory.
   @return Always returns 1, to continue executing.
 */
int minishell_cd(char **args)
{
  if (args[1] == NULL) {
    fprintf(stderr, "minishell: expected argument to "cd"n");
  } else {
    if (chdir(args[1]) != 0) {
      perror("minishell");
    }
  }
  return 1;
}
/**
   @brief Builtin command: print help.
   @param args List of args.  Not examined.
   @return Always returns 1, to continue executing.
 */
int minishell_help(char **args)
{
  int i;
  printf("Tianwei's minishell, version 1.01n");
  printf("These shell commands are defined internally.n");
  for (i = 0; i < minishell_mum_bultins(); i++) {
    printf("  %sn", builtin_str[i]);
  }
  return 1;
}
/**
   @brief Builtin command: exit.
   @param args List of args.  Not examined.
   @return Always returns 0, to terminate execution.
 */
int minishell_exit(char **args)
{
  return 0;
}

/**
  @brief Launch a program and wait for it to terminate.
  @param args Null terminated list of arguments (including program).
  @return Always returns 1, to continue execution.
 */
int minishell_launch(char **args)
{
  signal(SIGUSR2, killkillkill);
  int status;
  pid = fork();
  if (pid == 0) {
    // Child process
    childrunning = 1;
    if (execvp(args[0], args) == -1) {
      perror("minishell");
    }
    exit(EXIT_FAILURE);
  } else if (pid < 0) {
    // Error forking
    perror("minishell");
  } else {
    // Parent process
    do {
      waitpid(pid, &status, WUNTRACED);
    } while (!WIFEXITED(status) && !WIFSIGNALED(status));
  }
  return 1;
}
/**
   @brief Execute shell built-in or launch program.
   @param args Null terminated list of arguments.
   @return 1 if the shell should continue running, 0 if it should terminate
 */
int minishell_execute(char **args)
{
  int i;
  my_str(args[0]);
  if (args[0] == NULL) {
    my_str("args[0] is NULLn");
    // An empty command was entered.
    return 1;
  }
  for (i = 0; i < minishell_mum_bultins(); i++) {
    if (strcmp(args[0], builtin_str[i]) == 0) {
        my_str("1n");
      return (*builtin_func[i])(args);
    }
  }
  my_str("0n");
  return minishell_launch(args);
}
#define MINISHELL_RL_BUFSIZE 1024
/**
   @brief Read a line of input from stdin.
   @return The line from stdin.
 */
char *minishell_readln(void)
{
  int bufsize = MINISHELL_RL_BUFSIZE;
  int position = 0;
  char* buffer = malloc(1024 * sizeof(char));
  int c;
  while (1) {
    // Read a character
    c = getchar();
    // If we hit EOF, replace it with a null character and return.
    if (c == EOF || c == 'n') {
      buffer[position] = '';
      return buffer;
    } else {
      buffer[position] = c;
    }
    position++;
    // If we have exceeded the buffer, reallocate.
    if (position >= bufsize) {
      fprintf(stderr, "minishell: Command line too long!n");
      exit(EXIT_FAILURE);
    }
  }
}

/**
   @brief Loop getting input and executing it.
 */
void minishell_loop(void)
{
  signal(SIGINT, int_handler);
  char* line;
  char** args;
  int status;
  do {
    printf("MINISHELL: /home/tianwei/$ ");
    line = minishell_readln();
    my_str("0n");
    my_str(line);
    args = my_str2vect(line);
    my_str(args[0]);
    my_str("0n");
    status = minishell_execute(args);
    my_str("1n");
    free(line);
    free(*args);
    free(args);
  } while (status);
}
/**
   @brief Main entry point.
   @param argc Argument count.
   @param argv Argument vector.
   @return status code
 */
int main(int argc, char **argv)
{
  // Load config files, if any.
  // Run command loop.
    minishell_loop();
  // Perform any shutdown/cleanup.
  return EXIT_SUCCESS;
}

这是my_str2vect函数的代码

#include "../../include/my.h"
char** my_str2vect(char* str){
 // Takes a string 
 // Allocates a new vector (array of string ended by a NULL), 
 // Splits apart the input string x at each space character 
 // Returns the newly allocated array of strings
 // Any number of ' ','t', and 'n's can separate words.
 // I.e. "hello ttn class,nhow are you?" -> {"hello", "class,", "how", "are","you?", NULL}
    int max_num_words = 0;
    int a = 0;
    int b = 0;
    int max_num_char = 0;
    while(str[a] != ''){ // find the number of words and the length of the longest word
        if(str[a] != ' ' && str[a] != 't' && str[a] != 'n'){
            ++max_num_words;
            ++a;
            ++b;
            while((str[a] != ' ' && str[a] != 't' && str[a] != 'n') && str[a] != ''){
                ++a;
                ++b;
            }
            if(b > max_num_char){
                max_num_char = b;
            }
            b = 0;
            while((str[a] == ' ' || str[a] == 't' || str[a] == 'n') && str[a] != ''){
                ++a;
            }   
        }
    }
    char** output = (char **)malloc(sizeof(char *) * (max_num_words + 1)); // Allocate a 2D array first.
    for(int c = 0; c < max_num_words + 1; ++c){
        output[c] = (char *)malloc(sizeof(char) * (max_num_char + 1));
    }
    int i = 0;
    int j = 0;
    while(i < my_strlen(str) && j < max_num_words){ // Put the characters into the 2D array.
        int k = 0;
        while(i < my_strlen(str) && (str[i] == ' ' || str[i] == 't' || str[i] == 'n')){
            ++i;
        }
        while(i < my_strlen(str) && (!(str[i] == ' ' || str[i] == 't' || str[i] == 'n'))){
            ++i;
            ++k;
        }
        if(i-k < my_strlen(str) && j < max_num_words){
            my_strncpy(output[j], &str[i-k], k);
        }
        ++j;
    }
    output[j] = NULL;
    return output;
}

这是my_strncpy函数

#include "../../include/my.h"

char *my_strncpy(char *dst, char *src, int n)
{
    /* Same as my_strcpy except:
     *  Only copies n chars or until the end of src*/
    if(src != NULL && dst != NULL){
        int i = 0;
        while(i < n && src[i] != ''){
            dst[i] = src[i];
            ++i;
        }
        dst[i] = '';
    }
    return dst;
}

我没有尝试执行您的代码,但这是my_str2vect函数中的一见钟情的原因:

  • 在第一个while循环中,a仅在if中增加。如果您的线以空间开头
  • ,您可能会永远遇到一个永远的循环
  • 在第二个while循环中,您没有检查字符串''的结尾。这很可能是您崩溃的原因,但可能还有其他。

ps:由于您要解析字符串,因此应该看一下strtoksscanf,他们会享受您的生活

相关内容

  • 没有找到相关文章

最新更新