6

malloc()我刚开始使用 C 并且对和的性能问题知之甚少free()。我的问题是:如果我要在一个循环内调用malloc(),然后free()在一个while循环内调用,比如 20 次迭代,与在循环free() 外调用相比,它会运行得更慢吗?

我实际上是使用第一种方法为缓冲区分配内存,从文件中读取可变长度字符串,执行一些字符串操作,然后在每次迭代后清除缓冲区。如果我的方法导致大量开销,那么我想寻求一种更好的方法来实现相同的结果。

4

8 回答 8

15

肯定更慢。(但请记住,您需要平衡数量,malloc否则free会导致内存泄漏。)

如果长度不同,可以使用realloc扩展缓冲区大小。

void* v = malloc(1024);
size_t bufsize = 1024;

while(cond) {
   size_t reqbufsize = get_length();
   if (reqbufsize > bufsize) {
      bufsize = reqbufsize * 2;
      v = realloc(v, bufsize);
   }
   // you may shrink it also.

   do_something_with_buffer(v);
}

free(v);
于 2010-03-17T16:09:44.733 回答
7

如果在内部调用 malloc,则不能在循环外调用 free:

char * buffer;
for (int i = 0; i < num_files; i++) {
    buffer = malloc(proper_length(i));
    // do some things with buffer
}
free(buffer);

您将有 malloc'ednum_files时间,但只释放一次 - 除了最后一次之外,您泄漏了所有内存!

有两个主要选择 - 如果您知道适用于所有内容的大小,则在循环之前使用 malloc(或仅使用数组),或者使用 realloc:

char * buffer = NULL;
for (int i = 0; i < num_files; i++) {
    buffer = realloc(proper_length(i));
    // do some things with buffer
}
free(buffer);
于 2010-03-17T16:14:01.290 回答
6

对于 20 次迭代,您不必担心 malloc/free 的性能。

即使是更多(几个数量级),您也不应该开始考虑优化,直到您分析代码并了解什么是慢的。

最后,如果您要释放缓冲区,则无需先清除它。即使您要将 malloc/free 移到循环之外(使用 Justin 建议的最大缓冲区),您也不需要显式清除缓冲区。

于 2010-03-17T16:13:30.403 回答
3

如果您知道缓冲区的最大长度 - 或者可以设置一个合理的最大值 - 那么您可以为每次迭代使用相同的缓冲区。否则你在做什么应该没问题。

于 2010-03-17T16:07:29.103 回答
2

这取决于您需要缓冲区的用途。

您是否真的需要在每次迭代后清除它,或者\0末尾的 char 就足以标记字符串的结尾?毕竟这就是各种str库调用所使用的。

如果你真的需要清除它,你可以使用bzero(). 当然,在每次迭代中进行 malloc'ing 和 free'ing 是一种资源浪费,因为您可以愉快地重用缓冲区。

如果您要并行化 for 循环,即有多个并发线程使用它,则会出现不同的问题。

简单的,现实生活中的例子:使用水桶提水。假设你需要用那个桶做几次旅行:拿起它、使用它、放下它、再次拿起它、使用它等等……是否有意义?您可以尽可能多次重复使用存储桶。另一方面,如果您和更多人需要使用存储桶,您可以组织对存储桶的访问或需要更多存储桶。

最后的建议:现在不要担心表演。他们说早期优化是万恶之源,你很快就会明白为什么。

首先,了解问题:编写可以丢弃的代码。实验。其次,测试一下。确保它满足您的需求。三是优化。让循环运行一万次并测量需要多长时间。然后将 malloc 移到外面,再次测量(time如果在 UNIX 下使用 shell 命令)。第四,重写它,因为你的第一个实验很可能是一堆乱七八糟的try-retry-not working代码。

冲洗,重复。

ps:玩得开心。它应该是有趣的,而不是令人沮丧的。

于 2010-03-17T16:13:18.610 回答
1

通常任何可以移出循环的东西都应该是。既然可以做一次,为什么还要重复同样的动作呢?

Justin Ethier 是对的,分配一个可以轻松容纳最大字符串的缓冲区并重用它。

于 2010-03-17T16:13:24.660 回答
0

这取决于malloc和free的实现。

回答您的问题的最佳方法是建立一个基准......

于 2010-03-17T16:07:46.263 回答
0

更好地处理它。有一些伪代码:

#define BLOCK_SIZE 1024 // or about the bigger size of your strings.

char *buffer = (char *) malloc(BLOCK_SIZE) 

for(int i=0; i<20; i++)
{
   while (more bytes left to read)
   {
    read full string or BLOCK_SIZE bytes at max // most calls work this way
    proces bytes in buffer
   }
}

free(buffer);
于 2010-03-17T17:11:28.523 回答