我很困惑,在用malloc
分配内存时你必须提供一个大小,但是,有时会发生你不知道你需要的大小所以你要么分配大量的内存(由于你可能不会全部使用它,这听起来不太明智)或者当初始缓冲区大小太小时你使用realloc
。这两个选项有效吗?第二个听起来不错,但是,文档说realloc
...may move the memory block to a new location
听起来像一个非常糟糕的主意/难以处理的情况(例如,如果你有多个指针指向相同的地址realloc
它们都变得无效了。我是C的初学者,有人可以解释一下如何处理你有一个缓冲区的情况,这个缓冲区可能会或可能不会占用大量内存。
答案 0 :(得分:5)
有时候你不知道你需要的大小,所以你要么分配大量的内存(这听起来不太明智,因为你可能不会全部使用它)或者你当初始缓冲区大小变得太小时使用realloc。这两个选项有效吗?
原则上是的。实际上,使用现代操作系统内核和默认系统配置,使用 malloc 分配的数量并不重要。你看, malloc 分配地址空间,而不是内存。您可以根据需要分配尽可能多的地址空间,它实际上不会消耗内存;当然,操作系统将对该值进行多次健全性检查,例如在只有2GiB内存可用的系统(RAM +交换)上,您无法分配3GiB。通常的配置是,在一个块中可分配的最大块地址空间是可用系统内存的50%。
只有当你真正写东西时,操作系统才会为它保留内存。所以不要使用 calloc ,因为它初始化内存,即在其中写入内容。
所以,如果你不知道你需要多少钱,那么只需要一大块地址空间,你知道,根据所处理数据的特点,它可以很容易地保存你的任何东西。期待。一旦你在内存中获得它,你可以使用 realloc 来缩小分配。对于所有重要的实现, realloc 在缩小分配时永远不会移动数据。
需要注意的一件事是内存过量使用:假设您在具有4GiB RAM的系统上运行了5个进程,每个进程分配1GiB,但不立即写入它。操作系统会给他们这个地址空间,即它过度使用内存(就像航空公司过度使用飞行座位一样)。一段时间后,流程开始写入它。在某些时候,系统内存不足,操作系统必须对此做些什么:它将开始杀死进程,直到再次有“呼吸”的空间。
您可以关闭内存过量使用;强烈建议在高可靠性系统上使用。
答案 1 :(得分:3)
你是对的 - 这几乎是你的两个选择。你可以解决多个指针"抽象有点问题。如果不是直接传递malloc
返回的指针,而是将其粘贴到另一个数据结构中:
struct malloc_wrapper
{
void *p;
} wrapper;
wrapper.p = malloc(INITIAL_SIZE);
然后传递指向该数据结构的指针,您可以随时更改p
,并且任何共享指向新结构的指针的人都将相应地更新:
void *tmp = realloc(somepointertowrapper->p, NEW_SIZE);
/* check tmp to ensure it's not NULL. That indicates a failure
* to realloc and the original pointer passed into realloc
* remains valid.
*/
somepointertowrapper->p = tmp;