对于一个小型的嵌入式应用程序,我写了一些函数+结构作为字符串缓冲区(类似于 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
需要帮助,我很感激任何建议!
最佳答案
您增加缓冲区的方式效率很低。对于每一小段字符串,您重新分配()内存,这可能意味着分配新内存并复制“旧”内存的内容。这很慢并且会使您的堆碎片化。
更好的做法是以固定数量或固定百分比增长,即使新尺寸是旧尺寸的 1.5 倍或 2 倍。这也会浪费一些内存,但会保持堆的可用性并且不会产生太多副本。
这意味着您必须跟踪两个值:容量(分配的字节数)和长度(字符串的实际长度)。但这应该不会太难。
我会介绍一个函数“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
足够大。您可以根据需要选择不同的策略。
关于c - 在 stringbuffer 对象中手动分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7279903/