C: 分配比所需更多的内存是否有优势?

3
我正在开发一个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()都是虚假函数,用于强调我的问题的目的。我事先不知道结果“string”的大小(技术上讲,我正在处理的不是一个C样式/空终止字符串,而只是指向内存地址和长度/范围的指针),因此我需要动态调整结果字符串的大小(它可能比输入大,也可能比输入小)。

在我的第一次尝试中,我使用malloc()创建了第一个字节/字节的空间,然后每当需要附加另一个字节/几个字节时就会重新分配(realloc())...这样做也可以,但感觉这种方法将不必要地消耗操作系统资源,并且可能会导致反复移动内存中的字节。

所以我进行了第二次尝试,该尝试确定了经过单个转换单位(如FOO和BAR)后结果字符串的长度,并选择“首选分配大小”,例如256字节。例如,如果result_extent为250个字节,并且我处于FOO情况下,我知道我需要增加12个字节的内存(换行符、制表符和10个来自输入字符串的字节)——而不是重新分配260个字节的内存,我会寻找512个字节,押注自己可能会继续添加更多数据(因此我可以避免对realloc的调用)。

那么我的问题是:这种想法是否正确,或者说这是编译器/操作系统可能已经替我处理好的过早的优化?除了不浪费内存空间外,将内存按几个字节重新分配,还有其他优点吗?

我对单个转换实例可能会遇到的情况有一些粗略的想法,例如,最坏的情况可能是一个大小为2MB的输入字符串,其中包含几百个字节的标记,并且每个标记实例会增加50-100个字节的数据到结果字符串中(因此需要大约200次realloc来将字符串扩展50-100个字节,并且另外还要进行大约100次realloc,仅从输入字符串复制数据到结果字符串中,不涉及标记)。

如果您有关于这个话题的想法,请让我知道。谢谢!

1个回答

2

如您所知,realloc 可能会在每次调用时移动您的数据。这会导致额外的复制。在这种情况下,我认为最好分配一个足够大的缓冲区进行操作(上限)。最后,您可以分配结果所需的确切大小,并进行最终的复制/释放操作。这种方法更好,也不是过早优化。在我看来,在这种情况下使用 realloc 可能被认为是过早优化。


我想这里存在一个平衡点(如果我需要在内存中存储成千上万的结构体,可能最好采用更为保守的分配方法),但看起来这正是我所期望的确认。谢谢! - rguilbault

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接