C编程:malloc和循环中的free

我刚开始用C语言,对malloc()free()性能问题知之甚少。 我的问题是:如果我在一个while循环中调用malloc()后跟free() ,例如循环20次迭代,那么与在循环调用free()相比,它会运行得更慢吗?

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

绝对慢。 (但请记住,您需要平衡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); 

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

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

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

如果你在里面调用malloc,你不能在循环外调用:

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

你将有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); 

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

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

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

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

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

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

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

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

冲洗,重复。

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

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

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

这取决于malloc和free的实现。

回答你的问题的最好方法是建立一个基准……

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

 #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);