您当前的位置:首页 > 计算机 > 编程开发 > C语言

为什么编译程序提供了两个版本的malloc()函数?

时间:12-30来源:作者:点击数:

包含了头文件stdlib.h后,你就可以在程序中使用malloc()和free()函数了。这些函数是编译程序从C函数库中包含到你的程序中的。有些编译程序还提供了一个独立的库,你可以要求编译程序用其中的版本来代替标准库中的malloc()和free()版本(只需在命令行中加入类似一lmalloc这样的标志)。

malloc()和free()的替代版本和标准版本的功能完全一样,只不过前者被认为在对内存分配错误不那么宽容的代价下,能产生更好的执行效果。笔者在15年的C语言编程经历中从未使用过这些替代版本,但为了回答这个问题,笔者编写了一个大量使用malloe()和free()的简单的测试程序,并用一种非常著名的C编译程序,分使用和不使用malloc库两种情况对其进行了编译。结果笔者没有发现明显的差异,并且笔者怀疑该开发商在实现这两种版本时使用了相同的代码,因为两个版本的程序的大小是一样的。正因为如此,笔者也就不便指出该开发商的名字了。

以上的情况说明,也许不必去使用malloc()的其它版本,并且也不要指望它们会提高程序的性能。如果剖视(profiling)表明程序把大量时间花费在malloc()和free()上,并且通过改进算法也无法解决这个问题,那么你可以自己编写一个“缓冲池(pool)”分配函数,也许能提高程序的性能。

大量调用malloc()和free()函数的程序往往是为相同类型的数据分配内存和释放内存,这些数据具有固定的长度。当知道要分配和释放的数据的大小后,自己编写的缓冲池分配函数会比malloc()和free()运行得更快。一个缓冲池分配函数的工作方式是这样的:调用malloc()一次分配许多大小相同的结构,然后每次交付一个供使用。该函数通常从来不调用free(),它所使用的内存将一直保留到程序退出。例12.12给出了一个用于自定义类型struct foo的缓冲池分配函数。

例12.12一个缓冲池分配函数的例子

# include <stdio.h>
/*  declaration of hypothetical structure "foo"  */
struct foo {
       int   dummy1;
       char dummy2;
       long dummy3;
};
/*  start of code for foo pool allocator */
# include         <stdlib. h>
/*  number of foos to mallocO at a time  */
# define NFOOS 64
/*
 * A union is used to provide a linked list that
 * can be overlaid on unused foos.
 */
union foo_u {
        union foo_u     *next;
        struct foo       f;
};
static union foo_u        * free_list ;
struct foo  * alloc_foo()
 {
         struct foo     * ret = 0;
         if (!free_list)  {
                int    i;
                free_list = (union foo_u  * ) malloc(NFOOS
                                 * sizeof (union foo_u));
                if  (free_list)  {
                      for (i = 0;  i<NFOOS-1; i+ + )
                              free_list[i]. next =
                                     &iree_list[i + 1];
                      free_list [NFOOS -1 ]. next = NULL;
         if (free_list) {
               ret = &free_list ->f;
               free_list = free_list ->next;
         }
         return ret;
}
void free_foo(struct foo * fp)
{
         union foo_u   * up= (union foo_u  * ) fp;
         up ->next  = free_list)
         free_list = up;
}
int main(int argc, char  *  * argv)
{
         int       i;
         int       n;
         struct   foo    ** a ;
         if (argc <2) {
                 fprintf(stderr, "usage: %s f\n" ,  argv[0]);
                 fprintf(stderr. "where f is the number of");
                 fprintf(stderr, "'foo's to allocate\n" ) ;
                 exit(1);
         }
         i = atoi(argv[l]);
         a = (struct foo * * ) malloc(sizeof (struct  foo * ) *  i);
         for  (n = 0;  n<i; n+ + )
                 a[n] = alldc-foo() ;
         for  (n = 0j  n<i; n+ + )
                 free_foo(a[n]);
         return 0;
}

笔者用30000这样一个参数编译并运行了上述程序,并将其结果与用malloc()和free()代替alloc_foo()和free_foo()的一个类似的程序进行比较,发现前者使用的CPU时间为O.46秒,而后者为0.92秒。需要注意的是,使用缓冲池分配函数只能是最后的选择,它也许能提高速度,但它会造成内存的巨大浪费。此外,如果你不调用free(),而又没能小心地把从缓冲池中申请到的内存返回去,就会导致微妙的内存分配错误。 

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门