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

时间:2015-04-29 09:57:09

标签: c linux shell command-line segmentation-fault

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

  • 第一部分运行单个命令,如 ls,pwd 等。没有参数号 重定向。
  • 第二部分运行单个命令加上重定向。

这就是我们陷入困境的地方..我们编译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] = '\0';
    //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;
                }
            }               
        }
}

提前谢谢。

1 个答案:

答案 0 :(得分:2)

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

错误,您需要使用malloc预留空间:

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] = '\0';
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指针预留空间:

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

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