【问题标题】:Can't solve Segmentation fault (core dumped) in c无法解决c中的分段错误(核心转储)
【发布时间】:2015-07-08 12:51:32
【问题描述】:

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

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

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

函数.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

函数.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;
                }
            }               
        }
}

提前谢谢你。

【问题讨论】:

  • 调试器在哪里说分段错误发生了?
  • “无法解决分段错误”你试过什么?
  • “什么都没发生”表示错误没有自行解决,您的计算机“什么也没做”,gcc 没有帮助加载您的 c 源,更正错误并将其写回?另外,“我们实际上无法调试”是什么意思?你不知道怎么做?
  • @KBarg 为什么你实际上不能调试

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


【解决方案1】:
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);

【讨论】:

  • 非常感谢,尽管这些并没有阻止分段错误错误。
  • sizeof(*args) 是 deerenced 指针的大小(在这种情况下是指向 char 的指针)
  • 使用调试器,在控制台输入gdb yourprogram,然后输入run
  • 你说得对,这就是我们现在正在做的事情。非常感谢。
  • strdup()替换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';
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-05
  • 1970-01-01
  • 2021-05-24
  • 2022-01-14
  • 2017-02-25
相关资源
最近更新 更多