【问题标题】:Reading corrupt file, segmentation fault读取损坏的文件,分段错误
【发布时间】:2016-02-05 12:11:58
【问题描述】:

我通过传递一堆这样的目录来运行我的程序:

./myprogram *

每个目录都是一组单独的文件,我正在解析这些文件以获取数据,然后将其创建到电子表格中。每个目录都是电子表格的不同行。我只想将可靠的数据放入电子表格中,因此如果缺少条目,我会将其省略。它似乎在大多数目录上运行良好,但在某些目录上,我在我的一个解析函数中遇到了分段错误。

我注意到导致分段错误的每个文件都无法使用 gedit 打开。它给出了这个错误:

gedit 无法检测到字符编码。 请检查您是否尝试打开二进制文件。 从菜单中选择一个字符编码,然后重试。

但是,我可以使用 cat 或 tail 命令显示文件。

导致分段错误的具体函数是下面的 fscanf 函数,我用它一次读取一行。 (增加缓冲区的大小没有帮助)

 char *line = malloc(1000*sizeof(char));
 char *garbage = malloc(1000*sizeof(char));
 while(!feof(infile) )
 {
     fscanf(infile,"%[^\n]%[\n]",line,garbage);
     //parse the line
 }

有谁知道为什么文件可能无法用 gedit 打开吗?是否已损坏?有没有办法可以在解析函数中返回错误代码而不是段错误?

【问题讨论】:

  • 为什么你的程序崩溃了?失败是什么?您是否查看过回溯/使用过调试器?这看起来不像gedit 不能打开它更像gedit 不喜欢它,但我希望你能强迫它。如果您使用cat -A file,其他所有字符看起来都像^@吗?因为那会使它成为一个 UTF-16 文件。
  • 顺便说一句,这是一种奇怪的检测文件结尾的方法。
  • 不要使用 fscanf。 1000 字节不是一个大缓冲区。如果您在不包含 \n 的文件上运行缓冲区,则会崩溃。使用 fread,并解析缓冲区。
  • @Etan,当我运行 cat -A 时,有一大块 ^@ 字符,但文件的其余部分很好。
  • @Matt,你有没有更简单的方法一次读取一行,或者有没有办法防止溢出?另外,我在知道 feof 存在之前就写了这个,所以我会更新它。

标签: c linux bash


【解决方案1】:

fscanf() 中的缓冲区溢出。这可能会导致程序写入超出数组末尾,覆盖某处的指针,然后崩溃。

您的选择是:

使用fgets() 将一行读入输入缓冲区,并在必要时使用sscanf() 解析它,可能是您想要的,或者

告诉fscanf() 缓冲区的大小,例如fscanf( infile, " %999[^\n]%*[\n]", line );

此外,您几乎从不需要while (!feof(infile))。当它读取 past end-of-file 时,这将停止。

所以你真的应该把它改成:

static const size_t LINE_LEN = 1000;
while (fgets( line, LINE_LEN, infile ))
  /* Do stuff with line. */

或者

while ( 1 == fscanf( infile, " %999[^\n]%*[\n]", line ) )
  /* Do stuff with line. */

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多