我正在开发一个字符串密集型的Windows C项目:我需要将标记的字符串从一种形式转换为另一种形式。基本流程如下:
DWORD convert(char *point, DWORD extent)
{
char *point_end = point + extent;
char *result = memory_alloc(1);
char *p_result = result;
while (point < point_end)
{
switch (*point)
{
case FOO:
result_extent = p_result - result;
result = memory_realloc(12);
result += result_extent;
*p_result++ = '\n';
*p_result++ = '\t';
memcpy(result, point, 10);
point += 10;
result += 10;
break;
case BAR:
result_extent = p_result - result;
result = memory_realloc(1);
result += result_extent;
*result++ = *point++;
break;
default:
point++;
break;
}
}
// assume point is big enough to take anything I would copy to it
memcpy(point, result, result_extent);
return result_extent;
}
memory_alloc()和memory_realloc()是伪造的函数,以突出我的问题的目的。我事先不知道结果'字符串'会有多大(技术上,它不是我正在使用的C风格/空终止字符串,只是指向内存地址和长度/范围的指针),所以我'我需要动态调整结果字符串的大小(它可能比输入大,或者更小)。
在我的初始传递中,我使用malloc()为第一个字节/字节创建空间,然后随后realloc()每当我需要追加另一个字节/少量字节时......它可以工作,但感觉就像这样这种方法将不必要地敲击操作系统,并可能导致一遍又一遍地在内存中移动字节。
所以我进行了第二次传递,它确定了result_string在转换的单个单元之后的时间(上面用FOO和BAR情况说明)并选择“首选分配大小”,例如, 256个字节。例如,如果result_extent是250个字节并且我在FOO情况下,我知道我需要增加内存12个字节(换行符,制表符和输入字符串中的10个字节) - 而不是重新分配260个字节的内存,我达到512字节,对冲我的赌注,我可能会继续添加更多数据(因此我可以将自己的几个调用保存到realloc中)。
关于我的问题:后者的思维是否合理,或者编译器/操作系统可能已经为我提供了过早的优化?除了不浪费内存空间之外,根据需要将内存重新分配几个字节是否有优势呢?
我对单个转化实例中的预期有一些粗略的想法,例如:更糟糕的情况可能是2MB输入字符串,带有几百个字节的标记,这将导致每个标记实例将50-100字节的数据添加到结果字符串中(因此,说200个reallocs将字符串拉伸50- 100个字节,另外100个重新分配,只需将数据从输入字符串复制到结果字符串中,而不是标记)。
对此主题的任何想法将不胜感激。感谢
答案 0 :(得分:2)
您可能知道,realloc
可以在每次通话时移动您的数据。这导致额外的副本。在这种情况下,我认为分配一个最有可能足以进行操作的大缓冲区(上限)要好得多。最后,您可以为结果分配确切的金额并进行最终复制/免费。这是更好的,并不是过早的优化。在这种情况下,使用realloc的IMO可能被认为是过早优化。