释放函数内部或主内部的缓冲区

时间:2015-07-24 22:13:53

标签: c

今天我正在尝试编写程序,我意识到我需要在程序中的更多位置读取一个文件,但在我到达之前我有以下内容:

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

char *printFile(char *fileName){
    long int length;
    char *buffer;
    size_t size;
    FILE *file;

    file = fopen (fileName , "r" );


    fseek (file , 0 , SEEK_END);
    length = ftell (file);
    fseek (file , 0 , SEEK_SET);

    buffer = (char *) malloc (sizeof(char)*(size_t)length);
    if (buffer == NULL){
        fputs ("Memory error",stderr);
        exit (2);
    }


    size = fread (buffer,1,(size_t) length,file);
    if (size != (size_t)length){
        fputs ("Reading error",stderr);
        exit(3);
    }

    fclose (file);
    return buffer;
}

int main (void) {
    char *fileName = "test.txt";
    char *fileContent = printFile(fileName);

    printf("%s", fileContent);

    free(fileContent);

    return 0;
}

正如你所看到我在main函数中使用了free,在我意识到我的程序不行之后我决定在printFile函数中释放缓冲区,现在我有了这个:

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

char *printFile(char *fileName){
    long int length;
    char *buffer,*buffer2;
    size_t size;
    FILE *file;

    file = fopen (fileName , "r" );
    if (file == NULL){
        fputs ("File error",stderr);
        fclose (file);
        exit (1);
    }

    fseek (file , 0 , SEEK_END);
    length = ftell (file);
    fseek (file , 0 , SEEK_SET);

    buffer = (char *) malloc (sizeof(char)*(size_t)length);
    if (buffer == NULL){
        fputs ("Memory error",stderr);
        exit (2);
    }

    buffer2 = (char *) malloc (sizeof(char)*(size_t)length);
    if (buffer2 == NULL){
        fputs ("Memory error",stderr);
        exit (2);
    }

    size = fread (buffer,1,(size_t) length,file);
    if (size != (size_t)length){
        fputs ("Reading error",stderr);
        exit(3);
    }

    strcpy (buffer2, buffer);
    fclose (file);
    free(buffer);

    return buffer2;
}

int main (void) {
    char *fileName = "test.txt";
    char *fileContent = printFile(fileName);

    printf("%s", fileContent);

    return 0;
}

正如您可能已经注意到我使用了第二个指针(* buffer2)来复制其中第一个缓冲区的内容,然后将其释放到第一个缓冲区中。

我的问题是: 我的做法是对还是错?

2 个答案:

答案 0 :(得分:1)

欢迎使用内存管理!

你应该问的问题是:为什么你的第二种方法优于前者?您可以免费buffer,然后返回buffer2,有人必须释放buffer2,因此您处于与以前完全相同的位置,除非您复制了两次文件内容。 / p>

如果您不想在printFile()内分配内存,请强制调用者传入缓冲区。换句话说,将处理分配的责任转移到使用printFile()的任何代码。当然,现在调用者不得不担心分配足够大的缓冲区(尽管使用stat(2)很容易获得文件大小,或者像你一样使用stdio包装器)。

无论你最终使用什么方法,当你开始使用动态分配时,你就无法逃避内存管理:某个人必须负责释放内存。

答案 1 :(得分:1)

您的方法可以改进。

而不是

char *printFile(char *fileName);

使用两个功能

char *getFileContents(char *fileName);
void printFile(char *fileName);

理解getFileContents返回函数用户需要free d的内存。 printFile()和其他功能可以调用getFileContents(),可以随意调用内容,然后在内存中调用free()

此外,如果在阅读文件内容时出错,请返回NULL,而不是致电exit()

char *getFileContents(char *fileName)
{
   long int length;
   char *buffer;
   size_t size;
   FILE *file;

   file = fopen (fileName , "r" );
   if (file == NULL){
      fputs ("File error",stderr);
      return NULL;
   }

   fseek (file , 0 , SEEK_END);
   length = ftell (file);
   fseek (file , 0 , SEEK_SET);

   buffer = (char *) malloc (sizeof(char)*(size_t)length);
   if (buffer == NULL){
      fclose (file);
      fputs ("Memory error",stderr);
      return NULL;
   }

   size = fread (buffer,1,(size_t) length,file);
   if (size != (size_t)length){
      fputs ("Reading error",stderr);
      fclose (file);
      return NULL;
   }

   fclose (file);

   return buffer;
}

char *printFile(char *fileName)
{
   char* fileContents = getFileContents(fileName);
   if ( NULL != fileContents )
   {
      printf("%s", fileContents);
      free(fileContents);
   }
}