C编程:malloc并在循环中自由

时间:2010-03-17 16:03:40

标签: c free malloc

我刚开始使用C,对malloc()free()的性能问题知之甚少。我的问题是这样的:如果我在malloc()循环内调用free()后跟while循环,例如20次迭代,那么与调用{{1}相比,它会运行得更慢外面循环?

我实际上是使用第一种方法将内存分配给缓冲区,从文件中读取可变长度字符串,执行一些字符串操作,然后在每次迭代后清除缓冲区。如果我的方法导致很多开销,那么我想要一个更好的方法让我获得相同的结果。

8 个答案:

答案 0 :(得分:13)

绝对慢一点。 (但请记住,您需要平衡mallocfree的数量,否则会导致内存泄漏。)

如果长度不同,您可以使用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);

答案 1 :(得分:6)

对于20次迭代,你不应该担心malloc / free的性能。

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

最后,如果您要释放缓冲区,则无需先清除缓冲区。即使您要在循环外移动malloc / free(使用Justin建议的最大缓冲区),您也不需要明确清除缓冲区。

答案 2 :(得分:6)

如果您在内部调用malloc,则无法在循环外调用:

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

你将拥有malloc'ed num_files次,但只释放一次 - 你泄露了除了最后一个以外的所有内存!

有两个主要的选择 - 如果你知道一个适用于所有东西的大小,或者使用realloc,那么在循环之前的malloc(或者只是使用一个数组):

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

答案 3 :(得分:3)

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

答案 4 :(得分:2)

这取决于你需要什么缓冲区。

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

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

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

简单,真实的例子:使用水桶携带水。假设您需要使用该存储桶执行多次操作:拾取它,使用它,放下它,再次拾取它,使用它等等是否有意义?您可以尽可能多地重复使用该存储桶。 另一方面,如果您和更多人需要使用存储桶,您可以组织访问存储桶或需要更多存储桶。

最后的建议:现在不要担心表演。他们说早期优化是所有邪恶的根源,你很快就会理解为什么。

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

冲洗,重复。

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

答案 5 :(得分:1)

一般来说,任何可以移动到循环之外的东西都应该是。为什么只要你做一次就重复同样的动作?

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

答案 6 :(得分:0)

这取决于malloc和free的实现。

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

答案 7 :(得分: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);