在stringbuffer对象中手动分配

时间:2011-09-02 06:26:13

标签: c memory embedded malloc calloc

对于一个小型的嵌入式应用程序,我编写了一些函数+ struct作为String Buffer(类似于C ++中的std :: stringstream)。

虽然这样的代码工作正常,但有一些不那么小的问题:

  • 我以前从未在C中编写过手动分配使用增长内存的函数,因此我担心还有一些怪癖需要解决
  • 代码似乎分配了比实际需要更多的内存,这是 非常糟糕
  • 由于valgrind报告的警告,我已经在代码中的一个地方从malloc切换到calloc,这已经成功删除了警告,但我不完全确定我是否真的在使用它正确

我的意思是它分配的内容比实际需要的多(使用56k文件):

==23668== HEAP SUMMARY:
==23668==     in use at exit: 0 bytes in 0 blocks
==23668==   total heap usage: 49,998 allocs, 49,998 frees, 1,249,875,362 bytes allocated

......看起来不对......

有问题的代码在这里(太大而无法在SO上的<code>字段中复制):http://codepad.org/LQzphUzd

需要帮助,我很感激任何建议!

4 个答案:

答案 0 :(得分:2)

增长缓冲区的方式效率很低。对于每个小字符串,你可以使用realloc()内存,这意味着可以分配新内存并复制“旧”内存的内容。这很慢并且会破坏你的堆。

更好的是以固定数量或固定百分比增长,即使新尺寸为旧尺寸的1.5或2倍。这也浪费了一些内存,但会使堆更有用,而不是那么多副本。

这意味着您必须跟踪两个值:capacity(分配的字节数)和length(字符串的实际长度)。但这不应该太难。

我会介绍一个功能“FstrBuf_Grow”来处理所有这些。您只需使用要添加的内存量来调用它,FstrBuf_Grow将通过在必要时重新分配并至少根据需要重新分配容量来满足要求。

...

void FstrBuf_Grow(FstringBuf *buf, size_t more)
{
    while (buf->length + more) > buf->capacity
        buf->capacity = 3 * buf->capacity / 2;
    buf->data = realloc(buf->data, buf->capacity + 1);
}            

capacity乘以1.5,直到data足够大。您可以根据需要选择不同的策略。

答案 1 :(得分:1)

strncat(ptr->data, str, len);,在ptr->length = ((ptr->length) + len);之前移动并使用strncpy(ptr->data+ptr->length...。而ptr = NULL;中的Destroy是没用的。

“库”的代码似乎是正确的但请注意,您不断重新分配缓冲区。通常,您应该尝试很少增长缓冲区(例如,每次需要增长缓冲区时,使用max(2 *当前大小,4)作为新大小),因为增长缓冲区是O(n)。大内存分配可能是因为第一次分配一个小缓冲区。然后在更大的缓冲区中重新分配它。然后你需要在更大的缓冲区中重新分配它,这样堆就会增长。

答案 2 :(得分:0)

看起来你正在为每个追加重新分配缓冲区。只有当你想追求超过它能容纳的东西时,你才能成长吗?

重新分配时,您希望使用一种策略来增加缓冲区的大小,该策略可以在分配数量和分配的内存量之间进行最佳权衡。每次达到限制时,只需将缓冲区大小加倍即可能不适合嵌入式程序。

答案 3 :(得分:0)

通常对于嵌入式应用程序,最好分配1-3倍于最大消息大小的循环FIFO缓冲区。