【问题标题】:Segmentation fault in a for loop [duplicate]for循环中的分段错误[重复]
【发布时间】:2016-06-18 19:36:48
【问题描述】:

我遇到了这段代码的分段错误,我一辈子都无法弄清楚原因。我对指针比较陌生,所以它可能是显而易见的。该代码应该从标准输入中获取两行整数并以交替方式打印出来。我还没有完成打印出交替数字的代码的最后一部分。

    int main(){
        char *str1 = NULL;
        char *str2 = NULL;
        size_t sz = 0;
        int i;
        int x;
        char *rp1 = NULL;
        char *rp2 = NULL;
        getline(&str1, &sz, stdin);
        getline(&str2, &sz, stdin);
        char *result1;
        result1 = malloc(sizeof(*str1));
        char *result2; 
        result2 = malloc(sizeof(*str2));
        for(i = 0; (x = sscanf(str1, "%s ", &result1[i])) > 0; i++){
            if(x == EOF){
               return 0;
            }
            if(!isdigit(result1[i])){
               fprintf(stderr, "Error: invalid non-integer input\n");
               return 1;
            }
        }
        rp1 = malloc(i);
        rp1 = result1;
        for(i = 0; sscanf(str2, "%s ", &result2[i]) > 0; i++){
            if(!isdigit(result2[i])){
            fprintf(stderr, "Error: invalid non-integer input\n");
                return 1;
            }
        }
        rp2 = malloc(i);
        rp2 = result2;
        return 0;
  }

当我运行 gdb 时,它说我在第 25 行遇到了分段错误,这是第一个 for 循环。

编辑:所以我已经修复了 for 循环之前的 malloc 函数中的一个问题,但我仍然遇到分段错误。

【问题讨论】:

  • 在调试器下运行时,哪一行产生了段错误?
  • 是的,抱歉,当您回复时,我添加了正确的内容。 gdb 说第 25 行,这是第一个 for 循环。
  • 如果 str1 是一个指针,你为什么要 malloc 指针的大小?你不应该 malloc 它指向的大小吗?
  • 你认为这是在做什么:malloc(sizeof(str1));
  • 'result1 = malloc(sizeof(str1));'不像你认为的那样做:(

标签: c pointers segmentation-fault


【解决方案1】:

问题一:

sizeof(*str[1-2])sizeof(char) 相同。您正在为两个结果缓冲区分配一个字符,这显然是不够的。使用strlen(str[1-2]) + 1 这将为您提供一个与字符串中字符数相等的缓冲区,再加上一个用于空终止符的缓冲区。

问题 2:

getline() 分配一个缓冲区,在你完成它之后你应该分配给free(),你没有这样做,这实际上是内存泄漏。这不是您的问题的原因,但值得一提。你所有的malloc()'d 内存也是如此。

【讨论】:

  • 另外,'如果 *lineptr 设置为 NULL 并且 *n 在调用之前设置为 0,那么 getline() 将分配一个缓冲区来存储该行。对 getline() 的两次调用都引用了“sz”,对于第二次调用,它不会为零:(
  • 因为第一个参数是NULL,所以sz无论如何都会被忽略,他可能只是传递NULL而不是&sz
【解决方案2】:

这段代码有很多问题。其他人已经指出了malloc 的问题,但总的来说它是不必要的复杂。所有中间变量都可以去掉,直接访问str1str2

为了简化,我将把它简化为一个输入字符串,str。如果你想要两个,代码应该放在一个函数中而不是复制。

for + sscanf 循环似乎试图遍历 str 并检查它是否只包含数字。遍历字符数组直到最后遇到空字符会更好地完成此操作。

for(int i = 0; str[i] != '\0'; i++){
    ...do something with str[i]...
}

所以检查输入的每个字符是一个数字...

for(int i = 0; str[i] != '\0'; i++){
    if(!isdigit(str[i])){
        fprintf(stderr, "Error: invalid non-integer input '%c'\n", str[i]);
        return 1;
    }
}

这将失败,因为从标准输入读取的str 末尾有一个换行符。

【讨论】:

  • 谢谢!我将对此进行新的尝试,好像我有很多复杂的问题。
猜你喜欢
  • 2013-08-21
  • 1970-01-01
  • 2017-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-05
  • 2016-07-27
  • 1970-01-01
相关资源
最近更新 更多