apacheの1.3系と2系との互換では

とりあえず、apr_compat.hを2系でincludeしておくと良い。

マクロで定義したい場合は、とりあえず以下のマクロをやっとけば、1.3系のapを結構使えるはず。

#define ap_inline APR_INLINE
#define ap_md5_ctx_t apr_md5_ctx_t
#define ap_MD5Encode apr_md5_encode
#define ap_MD5Final apr_md5_final
#define ap_MD5Init apr_md5_init
#define ap_MD5Update apr_md5_update
#define ap_append_arrays apr_array_append
#define ap_array_cat apr_array_cat

続きを読む

apr_psprintfはかなり楽(apache2.x系)

apacheモジュールのメンテとかをしているんだが、メモリ管理系のapahceAPIはかなり楽だ。

本来なら、変数のサイズを常に気にしてcallocしたりfreeしたりする必要があるんだが、apacheAPIを使ってリソースpoolに管理を任せたら、その辺を全く気にしなくて良い。

sprintfするのも一苦労だけど、ここでもメモリ系を考えなくて良いAPIのapr_psprintfなどがあって、sprintfの第一引数は本来メモリを割り当てておく必要があるが、その必要も無い。

例えばこんなの。↓

if (x != NULL)
    buf_len += strlen(x);
else
    buf_len += NULL_LENGTH;
if (y != NULL)
    buf_len += strlen(y);
else
    buf_len += NULL_LENGTH;
buf = calloc(buf_len + 1, sizeof(char));
if  (buf == NULL)
    return "allocate error";
sprintf(buf, "x=%s y=%s", x, y)

free(buf);

この例だとbufには元々char方のxとかyだけを使っているが、ここにアドレスとかintを使うと、桁数計算とかでcharとしてのサイズがどれだけになるかとかが非常に面倒。

しかし、APIだと上のより面倒になりそうな実装がこんな風にかけちゃう。↓

buf = (char *)apr_psprintf(apr_pool_t *p,"x=%s y=%s z=%d adr=%x", x, y, z, adr);

こんな風に、整形した文字列に必要なサイズを自動で判断しリソースプールで確保してくれる。

こんなに楽だと、C書いてることを忘れそうだ・・・

apacheモジュールのメモリ管理

物欲日記ばっかり書かずに、たまにはお勉強の話でも。

fp = ap_pfopen(p, hoge.txt, "r");

if (fp == NULL) {
    fprintf(stderr, "%sは無いよ!\n", hoge.txt);
    return 1;
}

/* hoge.txt を色々弄って・・・*/

ap_pfclose(p, fp);

apacheのモジュールについて最近勉強しているので、やったことをメモしていこうと思ってます。色々調べてて、メモリとかファイルハンドル回りでほーほーと思ったことをいくつか。

  • apacheモジュールはC言語にも関わらず、メモリのリソース管理はapacheがよしなにしてくれる。
  • apacheはリソース管理のためにプール構造をとっている。
  • 新たに確保するメモリ等はプールに結び付けて管理されるので、プール破棄時にメモリも破棄されるわけですな。
  • というか、むしろメモリ開放のインターフェイスすら用意されてない。
  • リソースプールからアロケートされたメモリの開放はapache自身がすることになってる。
  • かってにプログラマがfree()とかしたらダメ。
  • リクエスト時などに、一時的にメモリ確保とかファイルハンドルを割り当てたい場合は、Request poolを生成して、そこから割り当てれば、レスポンス終了時にRequest poolが自動的に破棄されて、メモリとかも開放される。
  • 動的にメモリ確保する場合も、poolにから割り当てるので、NULLチェックの必要が無い。

ほーほー、ようするにCなのにメモリ管理は、用途によって用意された各種poolからpool生成して、そっからアロケートするから、プログラマが適当にメモリを弄るなってことなのね。