【问题标题】:fgets() causing segmentation fault when reading filefgets() 读取文件时导致分段错误
【发布时间】:2015-04-13 23:30:21
【问题描述】:

我正在尝试使用 fgets() 从文件中读取文本,但一直遇到分段错误。该程序读取整个文件,然后在读取最后一行后崩溃。任何帮助,将不胜感激。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *readFile(FILE *);

char *readFile(FILE *file){
    int *outputSize = (int *)malloc(sizeof(int));
    (*outputSize) = 1024;
    char *buf = (char *)malloc(sizeof(char)*1024);
    char *output = (char *)malloc(sizeof(char)*(*outputSize));
    *output='\0';
    while(fgets(buf,1024,file)){
        if(strlen(output)+strlen(buf)+1>(*outputSize)){
            printf("REALLOCATING...");
            (*outputSize) *=2;
            output = realloc(output,sizeof(char)*(*outputSize));
        }
        printf("BUFFER SIZE: %d\nBUFFER : %s\n",strlen(buf),buf);
        strcat(output,buf);
        printf("OUTPUT SIZE: %d\nOUTPUT: %s\n",strlen(output),output);

    }
    printf("FREEING...");
    free(outputSize);
    free(buf);
    return output;
}

【问题讨论】:

  • char *output = (char *)malloc(sizeof(char)*(*outputSize));*output=0;
  • if(strlen(output)+strlen(buf)+1&gt;(*outputSize)){
  • malloc 不会清除内存,因此将'\0' 放在第一个字符中可以保证第一个strcat 可以正常工作。如果你很幸运并且在output 中有一个初始的 0,那么你就不会注意到这个问题。如果最后一个 printf(...,output); 看起来正确,那么崩溃不在您发布的代码中。
  • @BLUEPIXY cmets 确实有帮助。可能还存在其他问题。
  • 重新分配可能仍然不够大:建议if(strlen(output)+strlen(buf)+1&gt;(*outputSize)){ --> while(strlen(output)+strlen(buf)+1&gt;(*outputSize)){ 尽管给定代码的逻辑,1 pass 应该就足够了。只需添加一些防御性编码即可。

标签: c fgets


【解决方案1】:

您的代码很难阅读,因此也很难调试。这就是您寻求帮助调试它的原因。

当您知道您正在阅读整个文件时,您不需要逐行读取文件。简化该代码并读取整个文件 - 这使得故障排除变得更加容易。 (这段代码甚至在更少的行中进行了所有错误检查,而且 IMO 更容易理解,即使没有告诉你发生了什么的 cmets 或调试语句)

char *readFile( FILE *file )
{
    struct stat sb;
    if ( !fstat( fileno( file ), &sb ) )
    {
        return( NULL );
    }

    if ( -1 == fseek( file, 0, SEEK_SET ) )
    {
        return( NULL );
    }

    char *data = malloc( sb.st_size + 1 );
    if ( data == NULL )
    {
        return( NULL );
    }

    /* this error check might not work in text mode because
       of \r\n translation */
    size_t bytesRead = fread( data, 1, sb.st_size, file );
    if ( bytesRead != sb.st_size )
    {
        free( data );
        return( NULL );
    }

    data[ sb.st_size ] = '\0';
    return( data );
}

头文件需要更新。

【讨论】:

  • 如果文件以文本模式打开,那么sb.st_size可能大于bytesReadsb.st_size 表示文件的真实字节大小,而文件输入可能会将类似 "\r\n" 的行结尾转换为 "\n"
  • @chux:是的。我错过了。啊。我讨厌这种翻译——它让你不可能知道你得到了每一个字节。谢谢,我更新了我发布的代码。
猜你喜欢
  • 2019-02-16
  • 1970-01-01
  • 2018-11-24
  • 1970-01-01
  • 2022-08-23
  • 2015-08-19
  • 1970-01-01
  • 2021-03-14
  • 1970-01-01
相关资源
最近更新 更多