namazu-dev(ring)


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: memory management (Re: AC_REPLACE_FUNCS)



Satoru Takabayashi さん:
> 現在は次のような安易な方針をとっています。
> 
>   * ユーザの入力 (検索式など) に対して長さ (byte 数) の制限を行う
>     - 入力の長さが制限の値より大きければその時点で警告を出して終了する
> 
>   * ユーザの入力を記録するために制限の値より大きい配列を確保している
> 
> 理屈ではこれで大丈夫のはずなんだけど、かなり怪しいです。もと
> もと、「実行したら検索をしてすぐ終了する」プログラムのつもり
> だったので、メモリ管理はいいかげんです。
> 
> [namazu-dev 105] で報告されているように、検索処理を繰り返し
> ているうちに、プロセスが緩やかに膨張していってしまう問題があ
> ります。
> 
> どこかで free()を忘れているのが原因だと思うんだけど、どうやっ
> て検出すればいいのだろう…。ご教示くださいませ > どなたか
> 
>   ...
> 
> ところで、ついさきほど EUC-JP の文字列を ISO-2022-JP に変換
> する euctojis() なる関数を作りました。EUC-JP から 
> ISO-2022-JP への変換では文字列が伸びるのできちんと扱うと大変
> です。
> 
> そこで、安易に「あらかじめ充分に大きな領域を確保しておくべし」
> という前提で実装してしまいました。こんなの言語道断ですね。;-)
> 

PHP の日本語対応で使っている物なんですが、
バッファーの大きさが足りなくなったら自動で再割り当てする
出力関数を作って、それを通してバッファに書くようにしています。


---------- i18n_ja_jp_filter.h の一部 --------------
/*
 * メモリに出力するoutput_function
 */
extern int memory_device_output(int c, void* data);
extern int wchar_device_output(int c, void* data);

#define MBFL_MEMORY_DEVICE_ALLOC_SIZE	64

struct memory_device {
	char* buffer;	/* (char*)0に初期化する必要がある。 */
	int length;		/* 0に初期化する必要がある。 */
	int pos;		/* 0に初期化する必要がある。 */
};

struct wchar_device {
	int* buffer;	/* (int*)0に初期化する必要がある。 */
	int length;		/* 0に初期化する必要がある。 */
	int pos;		/* 0に初期化する必要がある。 */
};

extern int memory_device_cat(struct memory_device *pd, const char *psrc);
extern int memory_device_ncat(struct memory_device *pd, const char *psrc, int len);



-------------- i18n_ja_jp_filter.c の一部 -----------------
/*
 * メモリに出力するoutput_function
 * あとで使用する。
 */
int
memory_device_output(int c, void* data)
{
    if (((struct memory_device*)data)->pos >= ((struct memory_device*)data)->length) {
        /* バッファの長さを調節 */
        int newlen = ((struct memory_device*)data)->length + MBFL_MEMORY_DEVICE_ALLOC_SIZE;
        char *tmp = (char*)realloc((void*)((struct memory_device*)data)->buffer, newlen);
        if (tmp == NULL) {
            return -1;
        }
        ((struct memory_device*)data)->length = newlen;
        ((struct memory_device*)data)->buffer = tmp;
    }

    ((struct memory_device*)data)->buffer[((struct memory_device*)data)->pos++] = (char)c;
    return c;
}

int
memory_device_cat(struct memory_device *pd, const char *psrc)
{
    int len;
    const char *p;

    len = 0;
    p = psrc;
    while (*p) {
        p++;
        len++;
    }

    if ((pd->pos + len) >= pd->length) {
        /* バッファの長さを調節 */
        int newlen = pd->length + len + MBFL_MEMORY_DEVICE_ALLOC_SIZE;
        char *tmp = (char*)realloc((void*)pd->buffer, newlen);
        if (tmp == NULL) {
            return -1;
        }
        pd->length = newlen;
        pd->buffer = tmp;
    }

    p = psrc;
    while (*p) {
        pd->buffer[pd->pos++] = *p++;
    }
    return 1;
}

int
memory_device_ncat(struct memory_device *pd, const char *psrc, int len)
{
    if ((pd->pos + len) >= pd->length) {
        /* バッファの長さを調節 */
        int newlen = pd->length + len + MBFL_MEMORY_DEVICE_ALLOC_SIZE;
        char *tmp = (char*)realloc((void*)pd->buffer, newlen);
        if (tmp == NULL) {
            return -1;
        }
        pd->length = newlen;
        pd->buffer = tmp;
    }

    while (len > 0) {
        pd->buffer[pd->pos++] = *psrc++;
        len--;
    }
    return 1;
}



-- 
sender: Tsukada Takuya (塚田 卓也)
town: inaba hizume, Nagano City (長野市稲葉日詰)