PHP 扩展开发的文章,我均已更新至《TIPI》(下面的博文可能已经过时,以 TIPI 上的内容为准)。
本篇可以说是TIPIT内存管理的笔记,仅仅供自己梳理知识使用,如果需要系统了解请直接阅读《TIPIT》
PHP属于高级语言,语言级别并没有内存的概念,在使用过程中完全不需要主动申请或释放内存。但是在扩展开发中我们需要使用C或C++来编写代码,就避免不了申请和释放内存了。
先大致了解下PHP内存管理分层图:
PHP的内存管理可以被看作是分层(hierarchical)的。 它分为三层:存储层(storage)、堆层(heap)和接口层(emalloc/efree)。 供扩展调用的则是接口层,这些宏的定义在Zend/zend_alloc.h
,它们与原生C函数的对应关系如下:
C语言原生函数 | PHP内核封装后的函数 |
void *malloc(size_t count); | void *emalloc(size_t count); void *pemalloc(size_t count, char persistent); |
void *calloc(size_t count); | void *ecalloc(size_t count); void *pecalloc(size_t count, char persistent); |
void *realloc(void *ptr, size_t count); | void *erealloc(void *ptr, size_t count); void *perealloc(void *ptr, size_t count, char persistent); |
void *strdup(void *ptr); | void *estrdup(void *ptr); void *pestrdup(void *ptr, char persistent); void *estrndup(const char *s, unsigned int length); void *pestrndup(void *ptr, unsigned int length, char persistent); |
void free(void *ptr); | void efree(void *ptr); void pefree(void *ptr, char persistent); |
这些宏相当于一个接口层或中间层,定义了一个高层次的接口,使得调用更加容易。它隔离了外部调用和PHP内部的内存管理,实现了一种松耦合关系。虽然PHP不限制这些原生的C函数的使用, 但是官方文档还是建议使用这些宏。
使用这些宏的优点是:任何分配的内存在偶然情况下如果没有被释放,则会在请求的最后被释放。因此,真正的内存泄漏不会产生。然而,不要依赖这一机制,从调试和性能两个原因来考虑,应当确保释放应该释放的内存。剩下的优点是在多线程环境下性能的提高,调试模式下检测内存错误等。还有一个重要的原因,你不需要检查这些内存分配函数的返回值是否为null。当内存分配失败,它们会发出E_ERROR错误,从而决不会返回到扩展。
参考
http://www.laruence.com/2009/04/28/719.html
http://www.php-internals.com/book/?p=chapt06/06-02-php-memory-manager