C 言語でのプログラミングでは、開発者がメモリ管理を自分で行う必要があります。 PHP はウェブサーバのモジュールとして使われることが多いので、 メモリリークを引き起こさないようにメモリ管理が特に重要となります。 さらに注意を要するのは、PHP がスレッド環境で使われる可能性があるということです。 この場合、グローバル変数が競合状態になる可能性があります。 スレッドグローバルなデータの扱いかたについての情報は、 スレッドの分離機能を扱う スレッドセーフなリソースマネージャ のドキュメントを参照ください。
これらに加え、さらに Zend Engine 独特のパターンとして注意しなければならないのは、 比較的短時間の間に zval 構造体やその他の小さなメモリブロックの確保と解放を 頻繁に繰り返すということです。PHP のメモリ管理では、 memory_limit にも注意を払わなければなりません。
これらの要件を満たすために Zend Engine は、 リクエスト単位のデータを処理するための特別なメモリマネージャを提供しています。 リクエスト単位のデータとは、単一のリクエストを処理するためにのみ必要となるデータで リクエストが終了する時点で解放されるものです。 拡張モジュールの作者は、通常は以下の表にあるルーチンを使うだけで済むことになります。 これらは利便性を考慮してマクロとして実装されていますが、 このドキュメントでは関数として扱います。
| プロトタイプ | 説明 | 
|---|---|
void *emalloc(size_t size) | 
      size バイトのメモリを確保する。 | 
     
void *ecalloc(size_t nmemb, size_t size) | 
      
       size バイトのバッファを
       nmemb 件ぶん作成し、ゼロで初期化する。
       | 
     
void *erealloc(void *ptr, size_t size) | 
      
       バッファ ptr のサイズを変更する。
       emalloc を用いて size バイトのメモリを確保する。
       | 
     
void efree(void *ptr) | 
      
       ptr が指すバッファを解放する。
       解放するバッファは emalloc で確保したものでなければならない。
       | 
     
       void *safe_emalloc(size_t nmemb, size_t size, size_t offset)
       | 
      
       size バイトのブロックを nmemb
       個、そしてそれに加えて offset バイトを保持するバッファを確保する。
       emalloc(nmemb * size + offset) と似ているが、
       それに加えてオーバーフロー対策の特別なプロテクトが施される。
       | 
     
char *estrdup(const char *s) | 
      
       NULL 終端の文字列 s を保持できる大きさのバッファを確保し、
       s をそのバッファにコピーする。
       | 
     
       char *estrndup(const char *s, unsigned int length)
       | 
      
       estrdup と似ているが、NULL 終端文字列の長さが事前にわかっている場合に使う。
       | 
     
注意: C 標準ライブラリの同等の関数群とは異なり、Zend Engine のメモリ管理関数はメモリの確保に失敗しても NULL を返しません。 そのかわりに、処理を放棄して現在のリクエストを終了させます。
   上でも説明したように、メモリをきちんと管理してメモリリークを防ぐことは非常に大切です。
   確保したメモリは、不要になったらすぐ解放するようにしましょう。
   安全策として、Zend Engine では、上の API 群で確保したメモリは
   リクエストの終了時にすべて解放するようになっています。
   --enable-debug オプションつきで PHP をビルドした場合は、
   これは警告を発生させます。
  
例1 PHP のメモリリーク警告
ZEND_FUNCTION(leak)
{
    long leakbytes = 3;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &leakbytes) == FAILURE) {
        return;
    }
    emalloc(leakbytes);
}
上の例の出力は、 たとえば以下のようになります。
[Thu Oct 22 02:14:57 2009] Script: '-' /home/johannes/src/PHP_5_3/Zend/zend_builtin_functions.c(1377) : Freeing 0x088888D4 (3 bytes), script=- === Total 1 memory leaks detected ===
注意: PHP の変数を扱う際には、変数用のメモリを emalloc で確保して参照カウンタに注意を払う必要があります。 詳細は 変数の作成 を参照ください。
注意: このリーク検出機能が働くのは、emalloc で確保したメモリブロックに対してのみです。 より詳細な解析を行うには、valgrind や libumem といったメモリチェッカーを使うことをおすすめします。 これらによる解析時には、PHP のメモリチェッカーを無効化することもできます。 そのためには、環境変数 USE_ZEND_ALLOC=0 を設定してから PHP を開始させます。