今天我试图写一个程序,我意识到我需要一个文件在我的程序中的更多地方读取,但在我到达那里之前,我有以下内容:
#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);
}
}