号外号外,新建Redis交流讨论群:332160890,欢迎加入!!
zmalloc介绍
这部分是用来申请内存的,之所以单独成了一部分在于redis希望能够将不同系统提供的api统一起来,另外还有一部分系统无法获取malloc数目,因此在这里也进行了一部分的封装;这部分内容很简单,实际上就是malloc, calloc, realloc, free几个操作的变形
代码分析
使用变量
used_memory,已使用的内存数;
malloc_thread_safe,分配内存线程是否安全;
used_memory_mutex,已使用内存数变量互斥锁;
代码分解
zmalloc_default_oom,默认的内存溢出响应函数
static void zmalloc_default_oom(size_t size) {
fprintf(stderr, "zmalloc: Out of memory trying to allocate %zu bytes\n",
size);
fflush(stderr);
abort();
}
zmalloc,这里面判断是否需要添加prefix_size,也就是将分配的内存大小写到分配内存的前部,根据实际需要大小执行malloc函数
void *zmalloc(size_t size) {
void *ptr = malloc(size+PREFIX_SIZE);
if (!ptr) zmalloc_oom_handler(size);
#ifdef HAVE_MALLOC_SIZE
update_zmalloc_stat_alloc(zmalloc_size(ptr));
return ptr;
#else
*((size_t*)ptr) = size;
update_zmalloc_stat_alloc(size+PREFIX_SIZE);
return (char*)ptr+PREFIX_SIZE; //有些系统无法知道分配内存大小,需要自己添加
#endif
}
zcalloc,这个函数与zmalloc的函数区别在于申请得到的内存是否初始化,zcalloc会初始化,zmalloc则是乱数据
void *zcalloc(size_t size) {
void *ptr = calloc(1, size+PREFIX_SIZE);
if (!ptr) zmalloc_oom_handler(size);
#ifdef HAVE_MALLOC_SIZE
update_zmalloc_stat_alloc(zmalloc_size(ptr));
return ptr;
#else
*((size_t*)ptr) = size;
update_zmalloc_stat_alloc(size+PREFIX_SIZE);
return (char*)ptr+PREFIX_SIZE;
#endif
}
zrealloc,这个函数是用来重新分配内存的,如果ptr为空,则直接申请内存即可,如果当前地址不能满足size大小的内存空间,则需要重新申请内存,然后将ptr中数据拷贝过去,返回新申请内存地址;如果当前地址满足,则扩大当前地址范围
void *zrealloc(void *ptr, size_t size) {
#ifndef HAVE_MALLOC_SIZE
void *realptr;
#endif
size_t oldsize;
void *newptr;
if (ptr == NULL) return zmalloc(size);
#ifdef HAVE_MALLOC_SIZE
oldsize = zmalloc_size(ptr);
newptr = realloc(ptr,size); //重新分配内存
if (!newptr) zmalloc_oom_handler(size);
update_zmalloc_stat_free(oldsize);
update_zmalloc_stat_alloc(zmalloc_size(newptr));
return newptr;
#else
realptr = (char*)ptr-PREFIX_SIZE;
oldsize = *((size_t*)realptr);
newptr = realloc(realptr,size+PREFIX_SIZE);
if (!newptr) zmalloc_oom_handler(size);
*((size_t*)newptr) = size;
update_zmalloc_stat_free(oldsize);
update_zmalloc_stat_alloc(size);
return (char*)newptr+PREFIX_SIZE;
#endif
}
zfree,释放内存;
void zfree(void *ptr) {
#ifndef HAVE_MALLOC_SIZE
void *realptr;
size_t oldsize;
#endif
if (ptr == NULL) return;
#ifdef HAVE_MALLOC_SIZE
update_zmalloc_stat_free(zmalloc_size(ptr));
free(ptr);
#else
realptr = (char*)ptr-PREFIX_SIZE;
oldsize = *((size_t*)realptr);
update_zmalloc_stat_free(oldsize+PREFIX_SIZE);
free(realptr);
#endif
}