# 機能設計書 181-カスタムアロケータ設定

## 概要

本ドキュメントは、libuvのカスタムメモリアロケータ設定機能（`uv_replace_allocator()`）の設計仕様を定義する。この機能により、libuv内部で使用されるメモリ確保・解放関数を利用者が独自に差し替えることが可能になる。

### 本機能の処理概要

**業務上の目的・背景**：libuvはデフォルトでC標準ライブラリの`malloc`/`realloc`/`calloc`/`free`を使用するが、組み込みシステムや大規模サーバーアプリケーションでは、メモリプール管理、メモリ使用量の追跡、カスタムメモリアリーナの利用、メモリリーク検出などの理由からメモリアロケータのカスタマイズが必要となる場合がある。本機能はそのような要件に対応するために、libuv内部のメモリ管理関数を一括で差し替える手段を提供する。

**機能の利用シーン**：
- メモリプールを使用する組み込みシステムでの利用
- jemalloc、tcmalloc等の高性能アロケータへの差し替え
- メモリ使用量のプロファイリング・モニタリング
- メモリリーク検出ツールとの統合
- Node.jsなどのランタイム環境でのV8ヒープとの統合

**主要な処理内容**：
1. 4つのメモリ管理関数ポインタ（malloc、realloc、calloc、free）のNULLチェックバリデーション
2. 内部静的構造体`uv__allocator`への関数ポインタの一括設定
3. 以降のlibuv内部でのメモリ確保・解放が差し替え後の関数経由で行われる

**関連システム・外部連携**：libuv内部のすべてのメモリ確保処理（`uv__malloc`、`uv__realloc`、`uv__calloc`、`uv__free`）が影響を受ける。Node.jsではV8エンジンのメモリ管理と統合するためにこの機能が使用される。

**権限による制御**：なし。ただし、プロセスの初期化フェーズで一度だけ呼び出すことが推奨される。スレッドセーフではないため、並行アクセスには注意が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 29 | その他ユーティリティ | 主機能 | uv_replace_allocator()によるメモリアロケータ置換のAPI定義 |

## 機能種別

設定処理（内部状態の変更）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| malloc_func | uv_malloc_func (void*(*)(size_t)) | Yes | カスタムmalloc関数ポインタ | NULLの場合UV_EINVALを返す |
| realloc_func | uv_realloc_func (void*(*)(void*, size_t)) | Yes | カスタムrealloc関数ポインタ | NULLの場合UV_EINVALを返す |
| calloc_func | uv_calloc_func (void*(*)(size_t, size_t)) | Yes | カスタムcalloc関数ポインタ | NULLの場合UV_EINVALを返す |
| free_func | uv_free_func (void(*)(void*)) | Yes | カスタムfree関数ポインタ | NULLの場合UV_EINVALを返す |

### 入力データソース

呼び出し元プログラムが提供する関数ポインタ。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | int | 成功時は0、失敗時はUV_EINVAL |

### 出力先

呼び出し元への戻り値。副作用として内部静的変数`uv__allocator`が更新される。

## 処理フロー

### 処理シーケンス

```
1. 入力バリデーション
   └─ malloc_func、realloc_func、calloc_func、free_funcのいずれかがNULLの場合、UV_EINVALを返す
2. アロケータ構造体の更新
   └─ uv__allocator.local_malloc = malloc_func
   └─ uv__allocator.local_realloc = realloc_func
   └─ uv__allocator.local_calloc = calloc_func
   └─ uv__allocator.local_free = free_func
3. 成功コード返却
   └─ 0を返す
```

### フローチャート

```mermaid
flowchart TD
    A[開始: uv_replace_allocator] --> B{malloc_func == NULL OR<br/>realloc_func == NULL OR<br/>calloc_func == NULL OR<br/>free_func == NULL?}
    B -->|Yes| C[UV_EINVALを返す]
    B -->|No| D[uv__allocator.local_malloc = malloc_func]
    D --> E[uv__allocator.local_realloc = realloc_func]
    E --> F[uv__allocator.local_calloc = calloc_func]
    F --> G[uv__allocator.local_free = free_func]
    G --> H[0を返す]
    C --> I[終了]
    H --> I
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-181-1 | 全関数必須 | 4つのアロケータ関数はすべて非NULLでなければならない | 常に適用 |
| BR-181-2 | 一括置換 | 4つの関数は一括で置換される（部分的な差し替えは不可） | 常に適用 |
| BR-181-3 | errno保持 | free関数呼び出し時にerrnoが保持される（uv__free内で対応） | free関数呼び出し時 |
| BR-181-4 | size=0時のmalloc | uv__mallocはsize=0の場合NULLを返す | size引数が0の場合 |
| BR-181-5 | size=0時のrealloc | uv__reallocはsize=0の場合、ptrをfreeしてNULLを返す | size引数が0の場合 |

### 計算ロジック

特になし。

## データベース操作仕様

### 操作別データベース影響一覧

該当なし（データベースを使用しない）。

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_EINVAL | バリデーションエラー | いずれかの関数ポインタがNULL | 4つすべての関数ポインタを非NULLで渡す |

### リトライ仕様

リトライ不要。正しいパラメータで再呼び出しすれば成功する。

## トランザクション仕様

該当なし。スレッドセーフではないため、初期化フェーズでの単一スレッドからの呼び出しが推奨される。

## パフォーマンス要件

関数ポインタの代入のみであるため、O(1)の定数時間で完了する。パフォーマンスへの影響は実質なし。ただし、差し替え後のカスタムアロケータの性能がlibuv全体のパフォーマンスに影響する。

## セキュリティ考慮事項

- カスタムアロケータが不正な実装である場合、メモリ破壊やクラッシュの原因となる
- calloc関数はゼロ初期化を行うことが期待される（セキュリティ上重要）
- free関数がerrnoを変更する可能性があるため、libuv側でerrnoの保存・復元を行っている

## 備考

- デフォルトのアロケータはC標準ライブラリの`malloc`/`realloc`/`calloc`/`free`
- `uv__reallocf()`は`uv__realloc()`のラッパーで、失敗時に元のポインタも解放する安全なrealloc
- `uv__strdup()`、`uv__strndup()`もカスタムアロケータ経由でメモリを確保する
- 関数型の定義は `include/uv.h` の278-281行目

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、カスタムアロケータを格納する内部構造体と、関数ポインタの型定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | アロケータ関数ポインタの型定義を理解する |
| 1-2 | uv-common.c | `src/uv-common.c` | 内部構造体`uv__allocator_t`の定義と初期値を理解する |

**読解のコツ**: `typedef`で定義される4つの関数ポインタ型（`uv_malloc_func`、`uv_realloc_func`、`uv_calloc_func`、`uv_free_func`）が、それぞれC標準ライブラリの`malloc`、`realloc`、`calloc`、`free`と同じシグネチャを持つことに注目する。

#### Step 2: エントリーポイントを理解する

`uv_replace_allocator()`の実装を読み解く。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | uv-common.c | `src/uv-common.c` | uv_replace_allocator()の実装（バリデーションと代入） |

**主要処理フロー**:
1. **114-117行目**: 関数シグネチャ - 4つの関数ポインタを引数に取る
2. **118-121行目**: NULLチェック - いずれかの関数ポインタがNULLならUV_EINVALを返す
3. **123-126行目**: 内部アロケータ構造体の4フィールドに関数ポインタを設定
4. **128行目**: 成功時に0を返す

#### Step 3: 内部メモリ管理関数を理解する

差し替えたアロケータが実際に使用される内部関数を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | uv-common.c | `src/uv-common.c` | uv__malloc(), uv__free(), uv__calloc(), uv__realloc()の実装 |
| 3-2 | uv-common.c | `src/uv-common.c` | uv__reallocf(), uv__strdup(), uv__strndup()の実装 |

**主要処理フロー**:
- **75-79行目**: `uv__malloc()` - size>0の場合のみ`local_malloc`を呼び出す（size=0ならNULL返却）
- **81-90行目**: `uv__free()` - errnoを保存してから`local_free`を呼び出し、errnoを復元する
- **92-94行目**: `uv__calloc()` - `local_calloc`をそのまま呼び出す
- **96-101行目**: `uv__realloc()` - size>0の場合は`local_realloc`、size=0の場合はfreeしてNULL返却
- **103-112行目**: `uv__reallocf()` - `uv__realloc`の結果がNULLかつsize>0なら元のポインタをfree

#### Step 4: アロケータの宣言を理解する

内部ヘッダーでの関数プロトタイプ宣言を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | uv-common.h | `src/uv-common.h` | 内部アロケータ関数のプロトタイプ宣言 |

**主要処理フロー**:
- **388-394行目**: `uv__calloc`、`uv__strdup`、`uv__strndup`、`uv__malloc`、`uv__free`、`uv__realloc`、`uv__reallocf`のプロトタイプ宣言

### プログラム呼び出し階層図

```
uv_replace_allocator()                   [src/uv-common.c:114-129]
    |
    +-- uv__allocator (static struct) への代入
           |
           +-- uv__malloc()               [src/uv-common.c:75-79]
           |      +-- uv__allocator.local_malloc()
           |
           +-- uv__free()                 [src/uv-common.c:81-90]
           |      +-- uv__allocator.local_free()
           |
           +-- uv__calloc()              [src/uv-common.c:92-94]
           |      +-- uv__allocator.local_calloc()
           |
           +-- uv__realloc()             [src/uv-common.c:96-101]
           |      +-- uv__allocator.local_realloc()
           |      +-- uv__free()
           |
           +-- uv__reallocf()            [src/uv-common.c:103-112]
           |      +-- uv__realloc()
           |      +-- uv__free()
           |
           +-- uv__strdup()              [src/uv-common.c:55-61]
           |      +-- uv__malloc()
           |
           +-- uv__strndup()             [src/uv-common.c:63-73]
                  +-- uv__malloc()
```

### データフロー図

```
[入力]                          [処理]                         [出力]

malloc_func   --+
realloc_func  --+--> uv_replace_allocator() --> uv__allocator (static) --> 0 (成功)
calloc_func   --+       |                                                    |
free_func     --+       |                                              UV_EINVAL (失敗)
                        v
                  NULLチェック
                        |
                  +-----+-----------------------------+
                  v                                   v
            バリデーション失敗              uv__allocator構造体更新
            (いずれかNULL)                (4つの関数ポインタ設定)
                  |                                   |
                  v                                   v
            UV_EINVAL返却                   以降のlibuv内部メモリ操作
                                          (uv__malloc/uv__free等)で
                                          カスタム関数が使用される
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダー | uv_replace_allocator()のAPI宣言、関数ポインタ型定義（278-288行目） |
| uv-common.c | `src/uv-common.c` | ソース | uv_replace_allocator()の実装、内部メモリ管理関数の実装（41-129行目） |
| uv-common.h | `src/uv-common.h` | 内部ヘッダー | 内部メモリ管理関数のプロトタイプ宣言（388-394行目） |
