【问题标题】:Segmentation fault C in writing a shell program编写 shell 程序时的分段错误 C
【发布时间】:2014-02-26 08:35:31
【问题描述】:

在我添加额外的东西之前,我的代码运行良好,例如识别和处理 cd、>、> 和 |。您能否检查我的代码并查看错误发生在哪里? 顺便说一句,分配的要求最多只有 1 个管道。而且我认为问题是从 for 循环的某个地方开始的,因为我将 printf 放在它后面以检查它是否会打印 args[k],但确实如此,但随后出现了错误并且程序停止了。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>

int main()
{
  const int MAX_ARGS = 10;
  char *token[MAX_ARGS + 1]; /*assume max number of token <=10*/
  char *temp;
  char line[256], command[MAX_ARGS];
  char prompt[] = "sh2 % ";
  pid_t pid;
  int i=0, j,k, status;

  printf("%s", prompt);

  while (fgets(line, sizeof line, stdin) != NULL)
  {
    line[strlen(line)-1] = '\0';    /*get rid of \n*/
    token[0] = strtok(line," ");
    strcpy(command,token[0]);    
    temp = strtok(NULL," ");
    while (temp != NULL)    
    {
      i = i+1;
      token[i] = temp;            
      temp = strtok(NULL," ");
    }
    char *args[i+2];
    for (j = 0; j < (i+1); j++) 
    {
      args[j] = token[j];  
    }
    args[i+1] = NULL;

    if (!strcmp("exit",command))
      exit(0);
    if (!strcmp("cd", command))
    {
      int success;
      if (success = chdir(args[1]) <0)
      {
        printf("Failed to change dir.\n");
      }
    }
    else 
    {
      int piping = 0;
      int fd;
      for (k = 0; k < sizeof args; k++)
      {         
        if (!strcmp(">",args[k])) 
        {   
          fd = open(args[k+1],O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR | S_IXUSR);
      if (fd <0) { printf("Open file failed.\n");}
          else 
      {
       dup2(fd, 1);
       args[k] = '\0';
       fflush(stdout);      
       close(fd);
      }
    }
    if (!strcmp("<", args[k]))
    {
      fd = open(args[k+1], O_RDONLY);
      if (fd <0) {printf("Open file failed.\n");}
      else
      {
        dup2(fd, 0);
        args[k] = '\0';
        close(fd);
      }
    }
    if (!strcmp(">>", args[k]))
    {
      fd = open(args[k+1], O_APPEND | O_CREAT, S_IRUSR | S_IWUSR | S_IXUSR);
      if (fd <0) {printf("Open file failed");}
      else
      {
            dup2(fd,1);
        args[k] = '\0';
        fflush(stdout);
        close(fd);
      }
    }
    if (!strcmp("|", args[k]))
    {
      piping = 1; 
        }
      } /*end for*/
      if (!(piping))
      {        
         pid = fork();
         if (pid <0) {}
         else if (pid == 0)
         {
           if ( (status = execvp(command, args)) < 0 )
       {
         printf("Command not found\n");
       }
         }
         else /*parent*/
         {
           wait(&status);          
         } /*end parent*/ 
      }/*end if not pipe*/
      else /*its pipe*/
      {
        int pfd[2];
    pipe(pfd);
    fd = fork();
    if (fd < 0) {}
    else if (fd ==0)
    {     
      close(pfd[1]);
      dup2(pfd[0],0);
      close(pfd[0]);
      execvp(args[2],args[2]);
    } 
    else /*parent*/
    {
      close(pfd[0]);
      dup2(pfd[1],1);
      close(pfd[1]);
      execvp(args[0],args[0]);
    }
      }/*end pipe*/
    } /*end outter else*/    

    printf("%s", prompt);

  }/*end  while*/
  return 0;
}  

【问题讨论】:

  • 你的调试器说什么?
  • 这个循环:for (k = 0; k &lt; sizeof args; k++) 绝对是错误的 - args 是一个指针数组,但您正在迭代它的大小,单位为 bytes
  • -g -O0编译你的程序,在gdb运行你的程序,然后用bt命令打印一个回溯。这会告诉你什么是段错误。
  • 当您输入“backtrace”时它表明了什么? (假设这里是 gdb,但我认为这最终并不重要)。
  • 再一次,在gdb 中运行程序——这是一个调试器。它在 UNIX 中运行。它不是 UNIX 的替代品。这将帮助您找到问题并阻止世界和他的狗对您的帖子投反对票。如果您找不到问题,结果也将帮助我们帮助您。另外,请正确缩进您的代码(提示:indent -nut - &lt; yourfile.c | perl -p -i -e '{print " ";}' 会给您一些可以粘贴到 Stack Overflow 中的内容)

标签: c shell unix


【解决方案1】:
for (k = 0; k < sizeof args; k++)

这不是您遍历args 的方式:这将远远超出数组的末尾。你想要这样的东西:

num = sizeof(args) / sizeof(*args);
for (k = 0; k < num; k++)

或者,由于您将最后一个元素设置为NULL,您可以这样做

for (char **arg = args; *arg; arg++)

另请注意,您使用k 迭代直到数组末尾,然后使用k + 1,这很可能会导致问题。

【讨论】:

  • @VictorN 你真的应该听取那些敦促你使用 gdb 或其他东西的人的建议。它有一点学习曲线,但它可以提供很多帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-29
  • 1970-01-01
  • 1970-01-01
  • 2015-06-07
相关资源
最近更新 更多