【问题标题】:Segmentation Fault on fputsfputs 上的分段错误
【发布时间】:2015-09-18 00:32:03
【问题描述】:

总的来说,我对 C 和内存分配非常陌生。基本上我要做的是复制未知大小的输入文件的内容并使用递归反转它的内容。我觉得我非常接近,但是当我尝试放入我认为是文件的反转内容的内容时,我不断遇到分段错误(我认为是因为我认为我做对了...... )

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int recursive_back(char **lines, int lineNumber, FILE *input) {

   char *input_line = malloc(sizeof(char) * 1000);
   lines = realloc(lines, (lineNumber) * 1000 * sizeof(char));
   if(fgets(input_line, 201, input) == NULL) {
      *(lines + lineNumber) = input_line;
      return 1;
   }  
   else {
      printf("%d\n", lineNumber);
      return  (1+recursive_back(lines, ++lineNumber, input));

   }

}

void backward (FILE *input, FILE *output, int debugflag )   {
   int i;
   char **lines;                            //store lines in here
   lines = malloc(1000 * sizeof(char *) ); //1000 lines

   if(lines == NULL) {         //if malloc failed
      fprintf(stderr, "malloc of lines failed\n");
      exit(1);
   }

   int finalLineCount, lineCount;
   finalLineCount = recursive_back(lines, 0, input);

   printf("test %d\n", finalLineCount);

   for(i = finalLineCount; i > 0; i--) {     
      fputs(*(lines+i), output);            //segfault here
   }

}

我正在使用一个简单的输入文件来测试代码。我的输入文件有 6 行长,上面写着“这是一个测试输入文件”。实际输入文件正在另一个函数中打开并传递给后向函数。我已经验证了我的程序中的其他功能可以正常工作,因为我一直在使用不同的选项。这两个功能是我唯一遇到问题的功能。我做错了什么?

【问题讨论】:

  • 您在分配给lines 时滥用realloc(您已经为1000 个指针分配了足够的空间)。无论如何,如果你真的要在你的函数中重新分配给lines,那么它需要是一个三重指针(即char ***lines,并且你分配给*lines),否则更改将不可见在调用者中。
  • segfault 时的 finalLineCount 被标记为 7(比我的文件的输入总行数多 1)。

标签: c file recursion segmentation-fault fputs


【解决方案1】:

你的问题在这里:

lines = realloc(lines, (lineNumber) * 1000 * sizeof(char));

正如@ooga 所说。它至少存在三个不同的问题:

  1. 您正在重新分配recursive_back() 的局部变量 lines 指向的内存块,并将新地址(假设重新分配成功)存储回该局部变量.新位置不一定与旧位置相同,但指向它的唯一指针是在recursive_back() 末尾超出范围的局部变量。调用者对应的变量没有改变(包括调用者为recursive_back()本身时),因此在recursive_back()返回后不再依赖为有效指针。

  2. 您使用错误的类型分配空间。 lines 具有 char ** 类型,因此它指向的对象具有 char * 类型,但是您正在根据 char 的大小保留空间。

  3. 您没有保留足够的空间,至少在第一次调用时,lineNumber 为零。在该调用中,当请求的空间正好为零字节时,realloc() 的作用是释放lines 指向的内存。在随后的调用中,分配的空间总是比您认为分配的少一行。

如果您可以依赖输入最多有 1000 行,那么 realloc() 看起来完全没有必要,因此您应该考虑将其删除。如果您确实需要能够以调用者将看到的方式重新分配,则调用者需要将 pointer 传递给它的变量,以便recursive_back() 可以通过该指针修改它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-25
    • 1970-01-01
    • 1970-01-01
    • 2020-03-23
    • 2017-09-17
    • 2010-10-30
    • 2015-01-20
    • 1970-01-01
    相关资源
    最近更新 更多