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() 是假函数,以突出我的问题的目的。我事先不知道结果“字符串”会有多大(从技术上讲,它不是我正在使用的 C 样式/空终止字符串,只是指向内存地址和长度/范围的指针),所以我' 需要动态调整结果字符串的大小(它可能大于输入,也可能更小)。

在我最初的传球中,我使用 malloc() 为第一个字节/字节创建空间,然后在需要附加另一个字节/少数字节时使用 realloc() ......它有效,但感觉这种方法是不必要的锤击操作系统,并可能导致内存中的字节一遍又一遍地移动。

所以我进行了第二次传递,它确定了 result_string 在转换的单个单元之后将持续多长时间(上面用 FOO 和 BAR 案例说明)并选择一个“首选分配大小”,例如 256 字节。例如,如果 result_extent 是 250 字节并且我处于 FOO 情况,我知道我需要将内存增加 12 字节(换行符、制表符和输入字符串中的 10 字节)——而不是重新分配 260 字节的内存,我'd 达到 512 字节,对冲我可能会继续添加更多数据的赌注(因此我可以为自己节省一些对 realloc 的调用)。

关于我的问题:后一种想法是合理的,还是编译器/操作系统可能已经为我处理的过早优化?除了不浪费内存空间之外,根据需要将内存重新分配几个字节是否有优势?

我对在单个转换实例中可能期望的内容有一些粗略的想法,例如,更糟糕的情况可能是带有几百字节标记的 2MB 输入字符串,这将导致将 50-100 字节的数据添加到结果中字符串,每个标记实例(例如,200 次重新分配将字符串拉伸 50-100 字节,另外 100 次重新分配是由简单地将输入字符串中的数据复制到结果字符串中引起的,除了标记之外)。

对此主题的任何想法将不胜感激。谢谢

4

1 回答 1

2

您可能知道,realloc可以在每次通话时移动您的数据。这会产生额外的副本。在这种情况下,我认为分配一个很可能足以满足操作(上限)的大缓冲区要好得多。最后,您可以为结果分配确切的数量并进行最终复制/免费。这更好,根本不是过早的优化。在这种情况下,使用 realloc 的 IMO 可能被认为是过早的优化。

于 2013-01-10T03:21:05.677 回答