# 機能設計書 41-メモリ管理

## 概要

SQLiteにおける動的メモリアロケーションを統一的に管理し、メモリ使用状況の追跡、制限設定、および複数のアロケータ実装の切り替えを可能にする機能の設計書。

### 本機能の処理概要

SQLiteのメモリ管理機能は、データベースエンジン全体で使用されるメモリの割り当て・解放・再割り当てを一元的に制御する基盤機能である。

**業務上の目的・背景**：組み込みデータベースとして様々な環境で動作するSQLiteにとって、メモリ管理は最も重要な基盤機能の一つである。リソースが限られた組み込み環境から大規模サーバー環境まで、異なるメモリ制約に柔軟に対応する必要がある。また、メモリリークの検出やメモリ使用量の監視により、アプリケーションの安定性を確保する。

**機能の利用シーン**：
- データベース接続時のメモリプール初期化
- SQL文のパース・コンパイル時の一時メモリ割り当て
- クエリ実行時のワーキングメモリ確保
- キャッシュページの動的確保・解放
- アプリケーションがメモリ上限を設定したい場合

**主要な処理内容**：
1. メモリ割り当て（sqlite3_malloc, sqlite3Malloc）：指定サイズのメモリを確保し、使用統計を更新
2. メモリ解放（sqlite3_free, sqlite3DbFree）：確保したメモリを解放し、統計を更新
3. メモリ再割り当て（sqlite3_realloc, sqlite3Realloc）：既存メモリブロックのサイズを変更
4. Lookaside最適化：接続ごとの小規模メモリプールによる高速割り当て
5. ソフト/ハードヒープ制限：メモリ使用量の上限設定と監視
6. アラーム機構：メモリ上限接近時のキャッシュ解放トリガー
7. 複数アロケータ対応：システムmalloc、memsys5（バディアロケータ）の切り替え

**関連システム・外部連携**：
- OSのメモリ管理システム（malloc/free/realloc）
- ページキャッシュサブシステム（メモリ解放時の連携）
- ミューテックスサブシステム（スレッドセーフな操作）
- ステータス情報サブシステム（使用量追跡）

**権限による制御**：特になし（内部機能のためアプリケーションレベルの権限制御は不要）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | （内部機能） | - | API関数としてアプリケーションから呼び出し可能 |

## 機能種別

メモリアロケーション / リソース管理 / 統計追跡

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| n (nBytes) | int / u64 | Yes | 割り当てるメモリサイズ（バイト） | 0以下は無効、SQLITE_MAX_ALLOCATION_SIZE以下 |
| p (pOld) | void* | Yes | 解放/再割り当て対象のポインタ | NULL許容（解放時はno-op） |
| db | sqlite3* | No | データベース接続ハンドル | NULL許容（Lookaside不使用時） |
| limit | sqlite3_int64 | No | ヒープ制限値 | 負値は現在値取得のみ |

### 入力データソース

- アプリケーションコードからのAPI呼び出し
- SQLite内部サブシステムからの呼び出し

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 割り当てメモリ | void* | 確保されたメモリブロックへのポインタ（失敗時はNULL） |
| 以前の制限値 | sqlite3_int64 | ヒープ制限設定時の変更前の値 |
| 解放結果 | void | メモリ解放（戻り値なし） |

### 出力先

- 呼び出し元への戻り値
- グローバルステータス情報（SQLITE_STATUS_MEMORY_USED等）

## 処理フロー

### 処理シーケンス

```
1. メモリ割り当て（sqlite3Malloc）
   ├─ サイズ検証（0チェック、上限チェック）
   ├─ 統計モード判定
   │   ├─ 有効時：ミューテックス取得→mallocWithAlarm呼び出し→解放
   │   └─ 無効時：直接xMalloc呼び出し
   └─ 8バイトアライメント確認

2. メモリ解放（sqlite3_free）
   ├─ NULLポインタチェック（NULLなら即座にreturn）
   ├─ 統計モード判定
   │   ├─ 有効時：ミューテックス取得→統計更新→xFree→解放
   │   └─ 無効時：直接xFree呼び出し
   └─ 終了

3. Lookasideメモリ割り当て（sqlite3DbMallocRawNN）
   ├─ サイズがLookaside許容範囲か判定
   ├─ 小規模スロット（LOOKASIDE_SMALL）確認
   ├─ 通常スロット確認
   │   ├─ フリーリストから取得可能→返却
   │   └─ 不可→通常のsqlite3Malloc使用
   └─ 統計更新
```

### フローチャート

```mermaid
flowchart TD
    A[sqlite3Malloc呼び出し] --> B{n==0 または n>MAX?}
    B -->|Yes| C[NULL返却]
    B -->|No| D{bMemstat有効?}
    D -->|Yes| E[ミューテックス取得]
    E --> F[mallocWithAlarm]
    F --> G{アラーム閾値超過?}
    G -->|Yes| H[キャッシュ解放試行]
    H --> I{ハード制限超過?}
    I -->|Yes| J[NULL返却]
    I -->|No| K[xMalloc実行]
    G -->|No| K
    K --> L[統計更新]
    L --> M[ミューテックス解放]
    M --> N[ポインタ返却]
    D -->|No| O[直接xMalloc]
    O --> N
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-41-01 | アライメント保証 | 全ての割り当てメモリは8バイト境界にアライメント | 常時 |
| BR-41-02 | ソフト制限 | alarmThreshold超過時はキャッシュ解放を試行 | SQLITE_ENABLE_MEMORY_MANAGEMENT有効時 |
| BR-41-03 | ハード制限 | hardLimit超過時は割り当て失敗 | hardLimit設定時 |
| BR-41-04 | Lookaside優先 | 小規模割り当てはLookasideプールを優先使用 | db接続存在時 |
| BR-41-05 | OOMカスケード | 一度OOM発生すると同一接続の後続malloc全て失敗 | mallocFailed設定後 |

### 計算ロジック

**Lookasideメモリ範囲判定**:
```
isLookaside = (p >= db->lookaside.pStart) && (p < db->lookaside.pTrueEnd)
```

**memsys5サイズ切り上げ**:
```
for(iFullSz=szAtom; iFullSz<nByte; iFullSz*=2);
```

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

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

本機能はデータベーステーブルを直接操作しない（メモリ管理機能のため）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| SQLITE_NOMEM | メモリ不足 | xMallocがNULL返却 | sqlite3OomFault呼び出し、mallocFailedフラグ設定 |
| - | 割り当て失敗 | ハード制限超過 | NULL返却、ログ出力（xLog設定時） |
| - | 割り当て失敗 | サイズ>SQLITE_MAX_ALLOCATION_SIZE | NULL返却 |

### リトライ仕様

SQLITE_ENABLE_MEMORY_MANAGEMENT有効時、初回malloc失敗後にsqlite3MallocAlarm経由でキャッシュ解放を試行し、再度mallocを実行する。

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

メモリ操作自体はトランザクションの対象外。ただし、メモリ割り当て失敗時はトランザクションのロールバックにつながる可能性がある。

## パフォーマンス要件

- Lookaside使用時：ミューテックス取得不要で高速割り当て
- 統計モード無効時：直接xMalloc呼び出しで最小オーバーヘッド
- memsys5使用時：フラグメンテーション抑制のためRobsonの制約を満たす

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

- デバッグビルド時、解放済みメモリを0xAA/0x55でパターン埋め（use-after-free検出支援）
- SQLITE_MEMDEBUGビルド時、詳細なメモリ追跡とタイプチェック

## 備考

- Apple環境ではzone allocatorを使用（SQLITE_WITHOUT_ZONEMALLOCで無効化可能）
- SQLITE_ENABLE_MEMSYS5でバディアロケータを有効化（組み込み環境向け）
- Two-size Lookaside（通常サイズ+小規模スロット）で効率向上

---

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

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

### 推奨読解順序

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

メモリ管理のグローバル状態とLookaside構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | malloc.c | `src/malloc.c` | struct Mem0Global（45-55行目）：グローバル状態管理 |
| 1-2 | sqliteInt.h | `src/sqliteInt.h` | Lookaside構造体：接続ごとのメモリプール定義 |
| 1-3 | mem5.c | `src/mem5.c` | struct Mem5Global（92-132行目）：バディアロケータ状態 |

**読解のコツ**: Mem0Globalのmutex、alarmThreshold、hardLimit、nearlyFullの4フィールドがメモリ管理の中核状態を表す。

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

公開API関数から内部実装への呼び出しフローを把握。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | malloc.c | `src/malloc.c` | sqlite3_malloc/sqlite3_malloc64（316-327行目）：公開API |
| 2-2 | malloc.c | `src/malloc.c` | sqlite3Malloc（296-309行目）：内部割り当て関数 |

**主要処理フロー**:
1. **316-321行目**: sqlite3_malloc - 初期化確認とsqlite3Malloc呼び出し
2. **296-309行目**: sqlite3Malloc - サイズ検証、統計モード分岐、xMalloc実行
3. **246-290行目**: mallocWithAlarm - アラーム処理と統計更新

#### Step 3: Lookaside最適化を理解する

接続ごとの高速メモリプールの仕組みを理解。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | malloc.c | `src/malloc.c` | sqlite3DbMallocRawNN（643-690行目）：Lookaside優先割り当て |
| 3-2 | malloc.c | `src/malloc.c` | sqlite3DbFreeNN（419-457行目）：Lookasideへの返却 |

**主要処理フロー**:
- **649-656行目**: サイズがLookaside許容範囲か判定
- **658-668行目**: 小規模スロット（LOOKASIDE_SMALL）からの取得試行
- **670-680行目**: 通常スロットからの取得試行

#### Step 4: 低レベルアロケータ実装を理解する

システムmallocラッパーとバディアロケータの実装詳細。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | mem1.c | `src/mem1.c` | sqlite3MemMalloc（128-152行目）：システムmalloc使用時 |
| 4-2 | mem1.c | `src/mem1.c` | sqlite3MemSetDefault（277-289行目）：デフォルト設定 |
| 4-3 | mem5.c | `src/mem5.c` | memsys5MallocUnsafe（220-285行目）：バディ割り当て |
| 4-4 | mem5.c | `src/mem5.c` | memsys5FreeUnsafe（290-351行目）：バディ解放とマージ |

**主要処理フロー**:
- **mem1.c 128-152行目**: SQLITE_MALLOCSIZE有無による分岐
- **mem5.c 242行目**: サイズを2のべき乗に切り上げ
- **mem5.c 248-253行目**: 適切なサイズのフリーリスト検索
- **mem5.c 321-342行目**: 解放時のバディブロックマージ

#### Step 5: ヒープ制限とアラーム機構を理解する

メモリ使用量制限の仕組みを理解。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | malloc.c | `src/malloc.c` | sqlite3_soft_heap_limit64（95-123行目）：ソフト制限設定 |
| 5-2 | malloc.c | `src/malloc.c` | sqlite3_hard_heap_limit64（137-153行目）：ハード制限設定 |
| 5-3 | malloc.c | `src/malloc.c` | sqlite3MallocAlarm（217-222行目）：アラーム発火 |

**主要処理フロー**:
- **95-123行目**: ソフト制限設定と即時キャッシュ解放
- **260-276行目**: mallocWithAlarmでのアラーム閾値チェック

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

```
sqlite3_malloc() / sqlite3_malloc64()
    │
    └─ sqlite3Malloc()
           │
           ├─ [bMemstat有効時]
           │      └─ mallocWithAlarm()
           │             ├─ sqlite3StatusHighwater()
           │             ├─ sqlite3MallocAlarm() ─── sqlite3_release_memory()
           │             ├─ xMalloc()
           │             └─ sqlite3StatusUp()
           │
           └─ [bMemstat無効時]
                  └─ xMalloc()
                         │
                         ├─ [mem1.c] sqlite3MemMalloc()
                         │      └─ SQLITE_MALLOC() / malloc()
                         │
                         └─ [mem5.c] memsys5Malloc()
                                └─ memsys5MallocUnsafe()

sqlite3DbMallocRawNN()
    │
    ├─ [Lookaside利用可能]
    │      └─ Lookasideスロットから直接返却
    │
    └─ [Lookaside不可]
           └─ dbMallocRawFinish()
                  └─ sqlite3Malloc()
```

### データフロー図

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

サイズ要求(n) ─────▶ sqlite3Malloc() ─────────────────▶ メモリポインタ
                         │
                         ▼
                    ┌─────────────┐
                    │ Mem0Global  │
                    │ ・mutex     │◀───── 統計情報更新
                    │ ・threshold │
                    │ ・hardLimit │
                    └─────────────┘
                         │
                         ▼
                    ┌─────────────┐
                    │ xMalloc()   │
                    │ (mem_methods)│
                    └─────────────┘
                         │
           ┌─────────────┼─────────────┐
           ▼             ▼             ▼
    [mem1.c]       [mem2.c]       [mem5.c]
    システム        デバッグ       バディ
    malloc         malloc        アロケータ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| malloc.c | `src/malloc.c` | ソース | メモリ管理の主要実装、公開API、Lookaside処理 |
| mem1.c | `src/mem1.c` | ソース | システムmalloc/free/reallocのラッパー |
| mem2.c | `src/mem2.c` | ソース | デバッグ用メモリアロケータ（境界チェック等） |
| mem5.c | `src/mem5.c` | ソース | memsys5バディアロケータ（組み込み向け） |
| mem0.c | `src/mem0.c` | ソース | メモリ割り当てをゼロ化するスタブ |
| sqliteInt.h | `src/sqliteInt.h` | ヘッダ | sqlite3_mem_methods、Lookaside構造体定義 |
| sqlite3.h | `src/sqlite3.h` | ヘッダ | 公開API宣言（sqlite3_malloc等） |
