我正在试图弄清楚使用malloc和realloc从用户那里收集未知数量的字符,存储它们,以及只在最后打印它们的最佳方法。
我认为调用realloc太多次都不会那么聪明。 所以相反,我每次都会分配一定数量的空间 sizeof char * 100 在文件的末尾,我使用realloc来精确地拟合整个事物的大小。
你觉得怎么样?这是一个好方法吗? 你会走另一条路吗?请注意,我无意使用链表,getchar(),putchar()。 仅使用malloc和realloc是必须的。
答案 0 :(得分:3)
如果重新分配以适应所需的确切数据量,那么您将优化内存消耗。这可能会导致代码变慢,因为1)您获得额外的realloc调用; 2)您可能无法分配适合CPU对齐和数据缓存的数量。可能这也会导致堆分段问题,因为重复的reallocs,在这种情况下它实际上可能会浪费内存。
很难回答"最好的"一般来说,但下面的方法相当常见,因为它是降低realloc调用的执行速度和降低内存使用之间的良好折衷:
您分配一个细分受众群,然后跟踪该细分受众群的用户数据量。分配size_t mempool_size = n * _Alignof(int);
字节是个好主意,使用可被8整除的n
也是明智之举。
每次在此段中耗尽可用内存时,都会重新分配到mempool_size*2
个字节。这样你每次都可以将可用内存增加一倍。
答案 1 :(得分:0)
我认为调用realloc太多次都不会那么聪明。
你是怎么想出来的?因为真正了解的唯一方法是衡量绩效。
您的策略可能需要根据您从用户那里读取数据的方式而有所不同。如果您使用getchar()
,则每次读取字符时,您可能不希望使用realloc()
将缓冲区大小增加一个字符。但是,即使在这种情况下,良好的realloc()
也会比你想象的低效率低得多。我认为glibc实际上为响应malloc()
而给出的最小块大小是16个字节。因此,从0到16个字符并且每次重新分配不涉及任何复制。类似地,对于较大的重新分配,可能不需要分配新块,可以使现有块更大。不要忘记,即使是最慢的,realloc()
也会比人们输入的速度快。
大多数人不会采取这种策略。输入的内容可以通过管道传输,因此人们不能快速打字的论点不一定有效。通常,您会介绍容量的概念。您分配具有特定容量的缓冲区,当它满了时,您可以通过添加特定大小的新块来增加其容量(使用realloc()
)。初始大小和重新分配大小可以通过各种方式进行调整。如果您正在阅读用户输入,则可能会使用较小的值,例如256字节,如果您正在从磁盘或网络上读取文件,您可能需要更大的值,例如4Kb或更大。
增量大小甚至不需要是常量,您可以选择将每个所需重新分配的大小加倍。这是一些编程库使用的策略。例如,我相信哈希表的Java实现使用它,因此可能是数组的Cocoa实现。
事先不可能知道在任何特定情况下最佳策略是什么。我会选择一些感觉正确的东西然后,如果应用程序有性能问题,我会做测试来调整它。您的代码不一定是最快的,但速度足够快。
然而我绝对不会做的一件事是在内置分配器的顶部覆盖一个家庭滚动内存算法。如果你发现自己维护了一个你没有使用的块列表而不是释放它们,那么你做错了。这就是让OpenSSL陷入困境的原因。