【问题标题】:Linux C Shell, segmentation fault thrown by child processLinux C Shell,子进程引发的分段错误
【发布时间】:2016-01-16 06:05:04
【问题描述】:

我一直在尝试选择 C ​​来完成一项要求创建 C shell 的家庭作业。一个要求是所有命令都应该从子进程中执行。问题似乎是我的子进程死得太早了,而且我从来没有到达实际执行命令的代码部分。我的代码:

parseCommand.h

char *parseCommand(char str[]) {
    char * token;
    //get size of the input array. divide memory amount allocated to array by the size of the 1st element (which should be representative of other elements)
    size_t n = sizeof(str) / sizeof(str[0]); 
    char *args = malloc(n);
    printf("Splitting string \"%s\" into tokens:\n", str);
    token = strtok(str, " \n");
    int i = 0;
    while (token != NULL) {
        printf(":: %s\n", token);
        args[i++] = token;
        token = strtok(NULL, " \n");
    }
    printf("after while loop");
    args[i]=(char *) 0;
    return args;

}

ma​​in.c

//I probably don't need all these
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>

//Custom Libraries
#include "parseCommand.h"

char *parseCommand(char str[]);

int main() {

    char path[10] = "/bin/";//path to bash scripts
    int should_run = 1;
    while (should_run) {
        printf("yazan_shell>> ");
        fflush(stdout); //force the prompt to the output immediately
        char *cmdStr = (char *)malloc(40); //allocate space for array
        fgets(&cmdStr, 40, stdin); //save user input to cmdStr
        pid_t pid = fork(); //create 
        if (pid == 0) {
            printf("==> Child received: %s command. Executing...\n", &cmdStr);
            char *cmd = parseCommand(&cmdStr);//split user input by space
            printf("cmd: %s", &cmd);
            execvp(strcat(path, cmd[0]), cmd);//excecute the input cmd
        } else {
            int returnStatus;
            waitpid(pid, &returnStatus, 0); //parent waits for child process
            printf("==> Parent is silent!! PID: %d\n", pid);
            should_run = 0;
        }
        free(cmdStr); //deallocate cmdStr
    }
}

输出 1

yazan_shell>> ls -l
==> Child received: ls -l
 command. Executing...
Splitting string "ls -l
" into tokens:
:: ls
:: -l
==> Parent is silent!! PID: 5500

RUN FINISHED; Segmentation fault; core dumped; real time: 3s; user: 0ms; system: 0ms

几天前我刚开始学习 C,但我在谷歌搜索了 C 中的分段错误,似乎我要么取消引用未初始化的指针,要么试图访问已释放的内存。所以我尝试注释掉

free(cmdStr);

行,然后输出如下所示:

yazan_shell>> ls -l
==> Child received: ls -l
 command. Executing...
Splitting string "ls -l
" into tokens:
:: ls
:: -l
==> Parent is silent!! PID: 5601

RUN FINISHED; exit value 33; real time: 1s; user: 0ms; system: 0ms

我还尝试在 parseCommand.h 的 while 循环中移动 print 语句,但输出似乎也没有改变。我问过几位有空的 C++ 教授,但他们都无法查明错误。这里有没有人能给我一些关于我的错误的指示(呵呵)?

非常感谢您!

【问题讨论】:

  • 启用更多编译器警告。 fgets(&amp;cmdStr, ...) 无效。将&amp;cmdStr 传递给printf %s 无效。 strcat(..., cmd[0]) 无效。
  • args[i++] = token 无效。 args[i] = (char *)... 无效。基本上你代码中的每一个指针操作都是错误的。
  • 如果您使用 gcc,您应该(至少)使用以下内容:gcc -Wall -Wextra -pedantic 并修复所有警告。
  • @melpomene 感谢您指出。我会尝试自己解决这些问题。我仍在试图弄清楚如何正确使用指针。如果您能纠正我的指针用法,将不胜感激。
  • 我使用的 IDE (Netbeans) 确实会发出警告,但我不完全理解我在做什么才能理解警告的含义。但我会转而使用 GCC。感谢您的提示

标签: c linux shell process segmentation-fault


【解决方案1】:

有几个问题-

1.main -

char *cmdStr = (char *)malloc(40);  // don't cast it
fgets(&cmdStr, 40, stdin);        // don't pass address of cmdStr it is already a char *

这样就好 -

char *cmdStr =malloc(40); 
fgets(cmdStr, 40, stdin); 

2.也在这里-

char *cmd = parseCommand(&cmdStr);//split user input by space
printf("cmd: %s", &cmd);      //cmd is already a char * don't pass its address

这样写-

printf("cmd: %s", cmd); 

3.在你的函数char *parseCommand(char str[])当你计算元素的数量时-

size_t n = sizeof(str) / sizeof(str[0]); 

这不会按预期工作。所以在main 中计算n,然后将其传递给你的函数

【讨论】:

  • 我听从了您的建议,但似乎没有解决输出中的任何问题。孩子还是早死了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-24
相关资源
最近更新 更多