libevnet源码分析(2) --内存分配

写在前面:

​ 这个源码是分析libevent-2.0.20-stable, 并非最新版本的libevent,作者并没有全看源码,在这里会推荐以下参考的一些网站,也欢迎大家在不足的地方提出来进行讨论。

​ libevent源码分析

​ libevent深度剖析1

​ libevent深度剖析2

 

什么都没包装的内存管理

​ 默认情况下,libevent 使用 C 库的内存管理函数在堆上分配内存。通过提供 malloc、realloc和 free 的替代函数,可以让 libevent 使用其他的内存管理器。希望 libevent 使用一个更高效的分配器时;或者希望 libevent 使用一个工具分配器,以便检查内存泄漏时,可能需要这样做。

//mm-internal.h
void *event_mm_malloc_(size_t sz);
void *event_mm_calloc_(size_t count, size_t size);
char *event_mm_strdup_(const char *s);
void *event_mm_realloc_(void *p, size_t sz);
void event_mm_free_(void *p);
#define mm_malloc(sz) event_mm_malloc_(sz)
#define mm_calloc(count, size) event_mm_calloc_((count), (size))
#define mm_strdup(s) event_mm_strdup_(s)
#define mm_realloc(p, sz) event_mm_realloc_((p), (sz))
#define mm_free(p) event_mm_free_(p)

​ 当我们追溯这些文件,到event.c中,会看到这些所谓的函数,在没有自定义的情况下仅仅只是调用了C 的内存分配API

void *
event_mm_malloc_(size_t sz)
{
    if (_mm_malloc_fn)
        return _mm_malloc_fn(sz);
    else
        return malloc(sz);
}
void *
event_mm_calloc_(size_t count, size_t size)
{
    if (_mm_malloc_fn) {
        size_t sz = count * size;
        void *p = _mm_malloc_fn(sz);
        if (p)
            memset(p, 0, sz);
        return p;
    } else
        return calloc(count, size);
}
​
void *
event_mm_realloc_(void *ptr, size_t sz)
{
    if (_mm_realloc_fn)
        return _mm_realloc_fn(ptr, sz);
    else
        return realloc(ptr, sz);
}
void
event_mm_free_(void *ptr)
{
    if (_mm_free_fn)
        _mm_free_fn(ptr);
    else
        free(ptr);
}

尝试定义自己的内存管理函数

​ 看到上面的实现,一定会有人想问,上面的像_mm_free_fn到底是什么呢?我们要如何使用它呢?

static void *(*_mm_malloc_fn)(size_t sz) = NULL;
static void *(*_mm_realloc_fn)(void *p, size_t sz) = NULL;
static void (*_mm_free_fn)(void *p) = NULL;

​ 它们其实是event.c中的静态全局变量,所以我们仅只能通过下面的函数对其进行操作

void
event_set_mem_functions(void *(*malloc_fn)(size_t sz),
            void *(*realloc_fn)(void *ptr, size_t sz),
            void (*free_fn)(void *ptr))
{
    _mm_malloc_fn = malloc_fn;
    _mm_realloc_fn = realloc_fn;
    _mm_free_fn = free_fn;
}

​ 如果想编译生成的库含有上述宏和实现,就必须在编译定义_EVENT_DISABLE_MM_REPLACEMENT这个宏,这个宏的定义是靠./configure自动生成的event-config,h定义的,若想要取消自定义内存函数,可以在编Libevent

加入--disable-malloc-replacement。

 

不得不提的注意事项

  • 替换内存管理函数影响 libevent 随后的所有分配、调整大小和释放内存操作。所以,必

  • 须保证在调用任何其他 libevent 函数之前进行替换。否则,libevent 可能用你的 free 函数释放用 C 库的 malloc 分配的内存。

  • 你的 malloc 和 realloc 函数返回的内存块应该具有和 C 库返回的内存块一样的地址对齐。

  • 你的 realloc 函数应该正确处理 realloc(NULL,sz)(也就是当作 malloc(sz)处理)

  • 你的 realloc 函数应该正确处理 realloc(ptr,0)(也就是当作 free(ptr)处理)

  • 你的 free 函数不必处理 free(NULL)

  • 你的 malloc 函数不必处理 malloc(0)

  • 如果在多个线程中使用 libevent,替代的内存管理函数需要是线程安全的。

  • libevent 将使用这些函数分配返回给你的内存。所以,如果要释放由 libevent 函数分配和返回的内存,而你已经替换 malloc 和 realloc 函数,那么应该使用替代的 free 函数

其实这些条款看似复杂,其实就是一个两个问题:

​ 1.malloc realloc free要配套,否则加入你在自己申请的内存池分配空间,调用系统free,然后在下一次使用那块空间的时候,就会dump core

​ 2.在多线程的情况下要求线程安全

你可能感兴趣的:(libevent)