【问题标题】:Segmentation Fault - Custom Shell分段错误 - 自定义外壳
【发布时间】:2013-02-17 13:29:15
【问题描述】:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define BUF 1024        //I assume that the maximum number of arguments is 1024

main()
{
    char c;
    char *temp;
    char *arg[BUF];                 //the commands
    int i=1,j,k,iter=0;

    while(1)
    {
            i=1;
            iter=0;
            printf("CS21> ");
            temp = malloc(sizeof(char));
            while((c=fgetc(stdin))!='\n')
            {
                    temp = realloc(temp, i*sizeof(char));

                    temp[i-1]=c;
                    i++;
            }

            j=0;
            while(j<strlen(temp))
            {
                    if(temp[j]==' ')
                    {
                            j++;
                            continue;
                    }

                    if(temp[j]!=' ')  //Line 38: Same check performed as Line 42
                    {
                                    k=j;
                                    arg[iter] = malloc(sizeof(char));
                                    while(temp[k]!=' ')    //Line 42: Segmentation Fault here
                                    {
                                            arg[iter] = realloc(arg[iter],(k-j+1)*sizeof(char));
                                            arg[iter][k-j]=temp[k];
                                            k++;
                                    }
                                    iter++;
                                    k++;
                                    j=k;
                                    continue;
                    }
            }
    }
}

嗨, 以上是我的自定义 shell 代码中的代码示例。我还没有完成代码,以防万一你想知道程序会一直运行到无穷大。 现在,我在一行中遇到了分段错误(已被评论),但我不明白为什么。我在第 38 行执行与第 42 行相同的检查,但它没有在那里给出分段错误。谁能帮帮我?

一些提到的变量的目的如下: “temp”是一个指向内存位置的指针,该内存位置保存给 shell 的整个命令。 “args”是一个指针数组,每个指针指向一个内存位置,该位置包含命令中的各个参数。

例如,“temp”将保存字符串 - gcc hello.c -o hello,如果它已传递给我的 shell。 args[0] 将指向“gcc”,args[1] 将指向“hello.c”等等。

这就是这个代码示例的目的。消除“temp”中的空格后,它将所有参数存储在“args”中。当人员从 shell 调用 exit 命令时,while(1) 循环将退出。但这部分将单独完成。 现在有人可以帮我处理这个代码示例吗?

谢谢!

【问题讨论】:

  • 显然您正在访问超出数组的范围。做一些调试来检查索引的值。
  • 一个提示:您不要终止 temp 字符串。或arg 字符串。
  • 其实我是用gdb来隔离线路的。但是您还没有回答这个问题 - 它如何接受一条线,然后继续在完全相同的线(逻辑上相似)处给出分段错误?
  • @Karthik 在下面查看我的答案
  • 这是一个非常糟糕的做法。您应该始终添加空终止字符!

标签: c shell segmentation-fault


【解决方案1】:

您需要为temp 分配额外的一个字符空间,用于表示字符串结束的特殊'\0' 字符。

while((c=fgetc(stdin))!='\n')
{
    temp = realloc(temp, i*sizeof(char) + 1);  //1 more char space for '\0'
    temp[i-1]=c;
    i++;
 }
 temp[i] = '\0';  //Indicates the end of String

并不是arg 字符串也必须以'\0' 结尾。

这将防止您遇到的分段错误,但您可能想检查您的程序可能会失败的其他情况..

有关详细信息,请参阅this

【讨论】:

  • 好吧,如果它从来没有看到 '\n' 并且一直重新分配并分配给从最终重新分配返回的 NULL 指针,它可能会崩溃。
【解决方案2】:

我认为以下行:

arg[iter] = malloc(sizeof(char));

如果item 大于BUF,则会损坏k 的值。如果iter 为负数,它也会损坏temp 的值。这是因为ktemp 存储在堆栈上,有点靠近arg,写入超出其大小的arg 元素实际上可能会覆盖存储在附近的变量。

尝试在上述行前后打印ktemp,看看它们的值是否损坏。

【讨论】:

    【解决方案3】:

    当字符串中没有空格时(最后一个参数的情况),您在 while(temp[k]!=' ') 中有一个未完成的循环。如果 k > strlen(temp),则需要停止循环。

    只是我的评论:到底是谁在教按字节读取并在每个字符后重新分配?这很尴尬……

    【讨论】:

    • 谢谢 V-X!你的建议奏效了!顺便说一句,你能告诉我一个更好的方法来读取命令并执行相同的操作吗?
    • char* buffer; buffer = (char*)malloc(1024); fgets(buffer, sizeof(buffer), stdin); 你可以检查一下,如果字符串以换行符结尾并且输入更长,那么你可以重新分配缓冲区并读取另一部分。
    【解决方案4】:

    在一行

    while((c=fgetc(stdin))!='\n')
    {
            temp = realloc(temp, i*sizeof(char));
    
            temp[i-1]=c;
            i++;
    }
    

    您不会以空终止字符结束临时字符串

    然后你就超出了那个数组的范围

     while(temp[k]!=' ')    //Line 42: Segmentation Fault here
    




    换行

     temp[i-1]=c; to  temp[i-1]='\n';
    

    while(temp[k]!=' ') to while(temp[k]!='\0')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-19
      相关资源
      最近更新 更多