如何确定realloc需要分配多少内存?

4
我有一个关于应用程序设计的问题。 以下是伪代码:
char* buffer_to_be_filled = (char*) malloc(somesize);
fill_the_buffer(buffer_to_be_filled);
free(buffer_to_be_filled);

问题在于我不知道fill_the_buffer需要多少空间。
我正在考虑在fill_the_buffer函数内部解决问题。 如果需要,我可以重新分配空间;但是问题是,有没有办法找出我有多少可用空间?
这通常如何解决?我认为分配缓冲区的人也应该重新分配缓冲区,对吗?
注意:我正在使用fread函数填充缓冲区,因此我不知道需要多少空间。
4个回答

3
您的函数无法使用realloc对传递给它的指针进行重新分配内存,因为realloc不能保证返回与传递给它的相同的指针(新缓冲区可能太大而无法原地扩展)。典型的解决方案是让函数接受第二个参数来指定缓冲区的大小,并在缓冲区太小时返回错误代码。理想情况下,错误代码将告诉用户缓冲区需要多大,以便他们可以自己重新分配并重新调用该函数。例如,从snprintf的手册页面中(也有这个问题):
“snprintf()和vsnprintf()函数不会写入超过size字节(包括终止的空字符('\0'))。如果由于此限制而截断输出,则返回值是字符数(不包括终止的空字符),如果有足够的空间,则将被写入到最终字符串中。因此,返回值为size或更多表示输出已被截断。”

2

你必须将缓冲区大小传递到fill_the_buffer函数中。如果缓冲区不够大,你的函数必须返回一个错误值(例如 -1)。如果成功,你的函数可以返回写入字节的计数。这种方法是C语言的常见做法。


2
似乎fill_the_buffer()函数更适合知道如何最初维度化缓冲区和/或何时重新分配缓冲区以及增加多少。
因此,更改API可能是合适的: char * fill_the_buffer() 或者可能是 char * fill_the_buffer(size_t max_amount_caller_wants) 调用fill_the_buffer()的调用方仍然负责处理由函数返回的缓冲区,但是分配和维度化将留给函数的逻辑。
这种方法通常遵循将实现细节留给较低级别的想法,使上层更易读的思路。

好的,如果一个函数分配了一些东西,我检索它并负责释放,那么这仍然是一个好的“设计”,我知道它会起作用,我只是想确保这是一个常见的做法。 - Jan Vorcak
@javo 你可以这样做,但这并不是常见的做法。通常分配内存的函数也会释放它。你可以将缓冲区传递给一个函数来填充它,或者该函数在内部保留一个静态缓冲区,在下一次调用时被覆盖。 - Michael Mrozek
2
是的。我理解您试图在同一方法中保持分配和释放的担忧。然而,这种方法并不罕见;当使用此模式时,建议以更明确的方式命名函数,例如Get_Data_From_XYZ()或类似的名称,并显式地注释API,告知调用者在不再需要缓冲区时需要释放它。 - mjv

0

如果您没有分配免费内存的问题,我有一个建议:
在程序开始时使用malloc分配初始大小(尝试为此初始分配做出良好的猜测),然后在fill_the_buffer中,您可能需要分配更多的内存,或者您可能不需要所有已分配的内存。在第一种情况下,您可以按步骤(例如每次泄漏10MB)分配适当数量的内存(取决于您的应用程序和可用的RAM),然后继续填充缓冲区,直到您需要更多内存,并重复此过程,直到缓冲区填满。
在第二种情况下,您可以简单地使用realloc来减少缓冲区已分配内存的大小。
但是要注意使用realloc,特别是当您想增加缓冲区大小时,因为它通常会导致很大的开销(它必须找到足够大的空闲内存部分,然后将所有旧数据复制到新部分并释放旧部分)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接