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



今天我试图写一个程序,我意识到我需要一个文件在我的程序中的更多地方读取,但在我到达那里之前,我有以下内容:

#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)来复制它里面的第一个缓冲区的内容。

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

欢迎使用内存管理!

你应该问的问题是:为什么你的第二种方法优于前一种方法?你释放了buffer,但是你返回了buffer2,然后有人必须释放buffer2,所以你的位置和以前完全一样,除了你复制了两次文件内容。

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

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

你的方法还可以改进。

代替

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);
   }
}

最新更新