C语言 基于现有文件的文件缓冲区大小的 Malloc



在我的项目中,我需要将共享文件复制到一个名为share的目录中。我的想法是使用 fgets 和 fputs 复制此文件的包含:

FILE *fp;
int size;
char *fileBuff
fseek(fp,0,SEEK_END );
size=ftell(fp);
printf("Size of %s: %d bytes.n",path,size); // print correct size 
fileBuff=malloc(size); // mallocate the file buffer
printf("nsize of file buffer is %d",sizeof(fileBuff)); //always print 4!!
while(!feof(fp)){
    fgets(fileBuff,size,fp); // put into file buffer
}
printf("nsize of file buffer is %d",sizeof(fileBuff)); // also print 4!!
但是,文件缓冲区

不能分配错误,此文件缓冲区的大小始终为 4。 会发生什么?

更新:似乎有一些误会。sizeof() 如果只是为了让我检查文件缓冲区中是否存储了任何内容。我确实尝试了strlen(fileBuff),它总是给我1。

这是

错误的:sizeof(fileBuff) .这将是指针的大小,在您的系统上为 4。

不能使用 sizeof 来"提取"malloc() 返回的内存块的大小。你不能使用任何东西来提取那个大小,这在(标准)C 中根本不可能。您需要使用size值,即malloc()参数。

此外,ftell()返回 long ,而不是intmalloc()和各种I/O调用都可能失败,您需要考虑到这一点。

在我看来,使用文件大小的缓冲区

来执行简单的复制不是一个好主意;最好使用"合理"的缓冲区(其确切的最佳大小取决于许多因素),然后在循环中执行重复的读写对,直到您流式传输整个文件。

更新 有关代码的更多要点:

  1. 您谈到使用strlen()但代码也显示了fread()之后的sizeof
  2. 你谈到使用sizeof来"检查"缓冲区中是否有任何东西,这是不可能的;任何带有sizeof的表达式总是在编译时1时计算,它不能用于检查这样的动态事物。而且,同样,您不能使用它来计算malloc()返回的内存块的大小。
  3. 仅当文件是二进制文件并且在其最后一个位置包含"\0"时,在保存文件数据的缓冲区上使用 strlen()才能可靠地工作,否则您将有一个未终止的字符串,并且strlen()可能会调用未定义行为。
  4. 正如我所说,您需要检查malloc()是否返回 NULL ,如果它无法分配请求的内存块,它将这样做。

1 除了 C99 中的灵活数组,但让我们忽略它。

99 名开发人员现在会回答您正在采用指针的大小。我什至不必查看代码。

( 32 位)平台上指针 (char *) 的大小始终为 4。

不能使用 sizeof 来确定已为缓冲区分配了多少内存。

要检查指针是否已分配,请检查返回值 malloc()

fileBuff = malloc(size);
if (fileBuff == 0) {
   fprintf(stderr, "Error allocating %d bytes.n", size);
   abort();
}
sizeof

编译时计算,因为您要求sizeof filebuf这是一个char*编译器计算它是 4 个字节(因为指针的大小是 4 字节在您的平台上)并打印它。你所做的mallocsizeof无关。

除了 sizeof() 的不当使用之外,您还可以考虑 2 个想法:

如果只是复制文件:不要试图重新发明轮子,只使用 system() 函数并调用为此设计的操作系统程序(在 unix 上为 cp,在 DOS/Windows 上复制)。

如果这是出于训练目的,因此你坚持自己做:不要试图读取整个文件,然后再写出来,而是逐块读取和写入。使用较大的缓冲区大小只会导致使 CPU 缓存毫无价值。通常匹配文件系统缓冲区大小或其中的简单部分是 goot 块大小,因此伪代码应如下所示:

open input file for reading
open output file for writing
as long as read from input file BUFSIZE bytes and read bytes > 0
     do write read data to output file
close input file
close output file

(并且不要忘记在每次调用 I/O 例程后检查 I/O 错误!

最后注意:不要使用 fgets(),除非你确定它总是一个纯文本文件。如果你选择使用 fread()/fwrite(),即使它是一个二进制文件(而且速度也更快),你也会被保存。

相关内容

  • 没有找到相关文章

最新更新