无法解决 c 中的分段错误(核心已转储)

Can't solve Segmentation fault (core dumped) in c

我们正在编写一个必须模仿 Linux shell 的程序。 它由一些部分组成。每个部分都做前一部分所做的事情,再加上一些额外的东西。

这就是我们卡住的地方。我们编译 myShell 2 没有错误。但是当我们输入任何命令时,我们都会遇到分段错误。 很抱歉在这里写了几乎所有的代码(不包括 myShell 1),我们只是想确保您拥有所需的一切来告诉我们哪里错了。

functions.h

#ifndef FUNCTIONS_H
#define FUNCTIONS_H

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#define max 260

extern int argCounter(char *argLine,char *delim);
extern void myExec(char *argLine,int howMany,char *delim);
extern char **argArray(char* argLine,int howMany,char *args[],char *delim);
void myExecRedir(char **tokens,char* argLine, int howMany);
#endif

functions.c

#include "functions.h"


int argCounter(char *argLine,char *delim)
{
    char *temp;
    memcpy(temp,argLine,strlen(argLine));
    char *pointer = strtok(temp, delim);
    int counter = 0;
    while (pointer != NULL)
    {
        counter++;
        pointer = strtok(NULL, delim);
    }                               
    return counter; 
}

void myExec(char *argLine,int howMany,char *delim)
{
    char temp[max];
    memset(temp,0,max);
    char *args[howMany];
    argLine[strlen(argLine)-1] = '[=11=]';
    //argArray breaks the argLine and returns an array that contains each argument
    argArray(argLine,howMany,args,delim);
    execvp(args[0],args); 
    perror("ERROR: wrong command!");
}


char **argArray(char *argLine,int howMany,char *args[],char *delim)
{                               
    args[howMany] = NULL;
    char *pointer = strtok(argLine, delim);
    int counter = 0;
    while (pointer != NULL)
    {
        args[counter]=pointer;
        counter++;
        pointer = strtok(NULL, delim);
    }                               
    return args;    
}

void myExecRedir(char **tokens,char* argLine, int howMany)
{
    char *delim3="<";
    char *delim4=">";
    int howManyIn= argCounter(argLine,delim3);
    int howManyOut= argCounter(argLine,delim4);
    if(howManyOut= howManyIn)
    {
        int fdin = open(tokens[1],O_RDWR);
        int fdout = open(tokens[2],O_RDWR);
        if(dup2(fdin,fdout) >= 0)
        {
            tokens[1]=NULL;
            tokens[2]=NULL;
            execvp(tokens[0],tokens);
        }
        else
        {
            printf("ERROR in dup2\n");
        }
    }
    else if(howManyIn== 0) //means we only have > redirection
    {
        int fdout = open(tokens[1],O_RDWR);
        if(dup2(2,fdout) >= 0)
        {
            tokens[2]=NULL;
            execvp(tokens[0],tokens);
        }
        else
        {
            printf("ERROR in dup2\n");
        }
    }
    else                //means we only have  redirection
    {
        int fdin = open(tokens[1],O_RDWR);
        if(dup2(fdin,1) >= 0)
        {
            tokens[2]=NULL;
            execvp(tokens[0],tokens);
        }
        else
        {
            printf("ERROR in dup2\n");
        }
    }
}

myShell2.c

#include "functions.h"

int main()
{
    printf("myshell2>");
    pid_t pid,waitPid;
    //WE TRIED WITHOU ALLOCATING MEMORY AS WELL
    char *argLine = (char *)malloc(max);
    char **args = (char **)malloc(max);
    char **args2 =( char **)malloc(max);
    char **temp = (char **)malloc(max);
    char *delim="><";
    char *delim2=" ";
    int i,howMany,howMany2,status;
    while(fgets(argLine,max,stdin) != NULL)
        {
            howMany= argCounter(argLine,delim);//howMany redirections
            args=argArray(argLine,howMany,args,delim);

            if (howMany == 1)//means we are at myShell 1
            {
                howMany2= argCounter(argLine,delim2);
                if(howMany2 ==1)//checking if the command has any parameters (like ls -l)
                {
                    printf("myshell2>");
                    pid = fork();
                    if (pid < 0)    
                    {
                        perror("ERROR: Fork failed.\n");
                        return -1;
                    }
                    else if(pid == 0)
                    {
                        myExec(args[0],howMany2,delim2);

                        perror("ERROR: Child should never arrive here.\n");
                    }
                    else
                    {
                        waitPid = wait(&status);
                        if (waitPid == -1) 
                        {
                            perror("ERROR: Waitpid failed.\n");
                            return -1;
                        }
                    }
                }
                else
                {
                    printf("ERROR: Wrong number of Arguments!\n");//can't run on myshell 2
                    return(0);
                }
            }
            //means we have redirection (< or >)
            for (i=0; i<howMany; i++)
            {
                argArray(args[i],2,args2,delim2);//args2 contains the tokens without spaces(delim2)
                temp[i] = args2[0];
                howMany2 = argCounter(args[i],delim2);
                if(howMany2 > 1)        // eg. ls -l should not run here
                {
                    printf("ERROR: Wrong number of Arguments!\n");//myShell3 should be running this
                    return(0);
                }
            }
            printf("myshell2>");
            pid = fork();

            if (pid < 0)    
            {
                perror("ERROR: Fork failed.\n");
                return -1;
            }                   
            else if(pid == 0)
            {               
                myExecRedir(temp,argLine,howMany);
                perror("ERROR: Child should never arrive here.\n");
            }
            else
            {
                waitPid = wait(&status);
                if (waitPid == -1) 
                {
                    perror("ERROR: Waitpid failed.\n");
                    return -1;
                }
            }               
        }
}

提前致谢。

char *temp;
memcpy(temp,argLine,strlen(argLine));
char *pointer = strtok(temp, delim);
...

不对,需要用malloc预留space:

size_t len = strlen(argline);
char *temp = malloc(len + 1);
if (temp == NULL) return 0;
memcpy(temp, argLine, len);
/* NUL-terminate the string */
temp[len] = '[=11=]';
char *pointer = strtok(temp, delim);
...
free(temp);

或者您可以使用非标准函数(但在许多实现中可用)strdup:

char *temp = strdup(argline);
if (temp == NULL) return 0;
char *pointer = strtok(temp, delim);
...
free(temp);

char **args = (char **)malloc(max);

也是错误的,如果你需要为 n 指向 char 的指针保留 space 使用:

char **args = malloc(sizeof(*args) * n); /* don't cast malloc */

char **args = malloc(sizeof(char *) * n);