阅读后无法关闭文件 - C编程

时间:2017-04-04 19:22:45

标签: c file fclose

我编写了一个函数,它读取一个充满文本的文件,并继续将所有行连接成一个字符串。它可以工作,但fclose()指令在使用时会启动错误:

" *`./main'错误:双重免费或损坏(退出):0x00000000020fc330 * "然后是回溯和记忆图。

对于单行文件,它也很糟糕。

我该怎么办?

代码:

char* readFile(char* fileName){
FILE* myFile = fopen(fileName, "r");
if (myFile != NULL) {
    fseek(myFile, 0, SEEK_END);
    long l = ftell(myFile);
    fseek(myFile, 0, SEEK_SET);
    char* content = (char*)malloc((size_t)l * sizeof(char));
    if (content == NULL) return NULL;
    char * chain = (char*)malloc((size_t)l * sizeof(char));     
    while(fscanf(myFile, "%s\n", chain) != EOF || fscanf(myFile, "%s\t", chain) != EOF || fscanf(myFile, "%s ", chain) != EOF){
        strcat(content, chain);
    }
    free(chain);
    fclose(myFile);         
    return content;
} else return NULL;

}

4 个答案:

答案 0 :(得分:0)

最有可能的是,您对scanf()和/或strcat()的调用正在写入已分配缓冲区(内容或链)的末尾并破坏堆。当free()尝试释放'链'时,会发现腐败,导致错误消息和崩溃。

为了避免写入超出缓冲区的末尾,您需要准确知道每个调用将写入缓冲区的字节数。用fscanf()很难知道,除非你对文件中的内容有保证(通常你没有),所以你可能想要使用fread()代替,这样就可以指定最大字节数阅读。此外,在调用strcat()时,您需要确保第一个参数指向的缓冲区有足够的空间用于其现有内容以及要添加到其现有内容末尾的字符串的内容。如果你想确保避免覆盖,请考虑调用strncat()(因为strcat()无法知道缓冲区有多大,它会愉快地写出过短缓冲区的结尾 - 至少是strncat ()将在你在第三个参数中指定的字节数后停止写入)

答案 1 :(得分:0)

除了othjer注释之外,你应该避免在循环中使用strcat()。每次循环时,strcat都必须在字符串中搜索nul字符,这种搜索会越来越长。

一种更有效的方法是保持指向nul字符的指针,只需使用strcpy添加它,然后按指定的字符数增加指针。

答案 2 :(得分:0)

正如其他人所说,你的内容指针指向未初始化的内存,当你尝试strcat()时它可能包含垃圾。尝试使用calloc()代替,这会将所有字符设置为'\ 0'并允许您执行所需的操作。

考虑遵循Jeremy的建议并创建一个更有效的功能来做你想要的。现在你要分配两个大小与文件一样的缓冲区,并寻找令牌来填充其中一个巨大的缓冲区并将它们连接到另一个缓冲区中。你放弃分隔符后肯定会有足够的空间,但这是浪费了很多空间。

答案 3 :(得分:0)

发布的代码,如问题评论中所示,存在很多问题。

以下发布的代码可以纠正这些问题,干净地编译并执行所需的功能。

#include <stdio.h>   // fopen(), fclose(), fseek(), NULL, perror()
#include <stdlib.h>  // malloc(), free()
#include <string.h>  // strcat()

char* readFile( char* );

char* readFile( char* fileName )
{
    FILE* myFile = fopen(fileName, "r");

    if ( !myFile )
    {
        perror( "fopen for reading file failed" );
        return NULL;
    }

    // implied else, fopen successful

    if( 0 != fseek(myFile, 0, SEEK_END) )
    {
        perror( "fseek to end of file failed:" );
        return NULL;
    }

    // implied else, fseek successful

    long fileLength = ftell(myFile);
    if( -1 == fileLength )
    {
        perror( "ftell failed" );
        return NULL;
    }

    // implied else, ftell successful

    if( 0 != fseek(myFile, 0, SEEK_SET) )
    {
        perror( "fseek to start of file failed" );
        return NULL;
    }

    // implied else, fseek successful

    char* content = malloc((size_t)fileLength+1 );
    if (content == NULL)
        return NULL;

    // initialize the concatenated string to be empty
    content[0] = '\0';

    char * chain = malloc((size_t)fileLength+1);
    if ( chain == NULL)
        return NULL;

    while( fgets( chain, (int)fileLength, myFile ) )
    {
        strcat(content, chain);
    }

    free(chain);
    fclose(myFile);
    return content;
} // end function: readfile