# 機能設計書 141-エラー取得

## 概要

本ドキュメントは、libuvの動的ライブラリ操作におけるエラーメッセージ取得機能 `uv_dlerror()` の設計仕様を定義する。

### 本機能の処理概要

`uv_dlerror()` は、動的ライブラリの読み込み (`uv_dlopen`)、シンボル検索 (`uv_dlsym`) 等の操作で発生したエラーの説明文字列を取得する関数である。

**業務上の目的・背景**：動的ライブラリ操作は、プラグインシステムやモジュール動的読み込み等の仕組みで頻繁に使用される。操作失敗時に原因を特定するためのエラーメッセージ取得機能は、デバッグやユーザーへのフィードバックに不可欠である。libuvは各プラットフォーム（Unix系のdlopen/Windows系のLoadLibrary）の差異を吸収し、統一的なエラー取得インターフェースを提供する。

**機能の利用シーン**：`uv_dlopen()` でライブラリの読み込みに失敗した場合、あるいは `uv_dlsym()` でシンボル検索に失敗した場合に、エラーの詳細情報を取得するために使用される。ログ出力やユーザーへのエラー通知にも活用される。

**主要な処理内容**：
1. `uv_lib_t` 構造体の `errmsg` フィールドを確認する
2. `errmsg` が設定されている場合はそのエラーメッセージ文字列を返却する
3. `errmsg` が NULL の場合は "no error" という文字列を返却する

**関連システム・外部連携**：Unix系では POSIX の `dlerror()` システムコールから取得したメッセージ、Windows系では `FormatMessageA()` で整形されたシステムエラーメッセージが格納される。

**権限による制御**：権限による実行可否の制御は存在しない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 27 | 共有ライブラリ | 主機能 | uv_dlerror()による動的ライブラリ操作エラー取得のAPI定義 |

## 機能種別

情報取得処理（エラー情報のリードオンリー参照）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| lib | const uv_lib_t* | Yes | 動的ライブラリハンドル構造体へのポインタ | NULLの場合は未定義動作 |

### 入力データソース

`uv_lib_t` 構造体は、事前に `uv_dlopen()` や `uv_dlsym()` で操作されたライブラリハンドルである。内部の `errmsg` フィールドはこれらの関数によって設定される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | const char* | エラーメッセージ文字列。エラーが無い場合は "no error" |

### 出力先

呼び出し元への戻り値として返却される。返却されるポインタは `uv_lib_t` 構造体内部のメモリを指すため、`uv_dlclose()` 後は無効となる。

## 処理フロー

### 処理シーケンス

```
1. uv_lib_t構造体のerrmsgフィールドを確認
   └─ lib->errmsgがNULLでないかチェック
2. errmsgが設定されている場合
   └─ lib->errmsgをそのまま返却
3. errmsgがNULLの場合
   └─ リテラル文字列 "no error" を返却
```

### フローチャート

```mermaid
flowchart TD
    A[uv_dlerror 呼び出し] --> B{lib->errmsg != NULL?}
    B -->|Yes| C[lib->errmsg を返却]
    B -->|No| D["'no error' を返却"]
    C --> E[終了]
    D --> E
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-141-01 | エラー保持 | errmsgはuv_dlopen/uv_dlsymの失敗時にOS固有のエラーメッセージが格納される | ライブラリ操作失敗時 |
| BR-141-02 | デフォルトメッセージ | エラーが発生していない場合は "no error" を返す | errmsgがNULLの場合 |
| BR-141-03 | 繰り返し取得可能 | 同じエラーメッセージを何度でも取得可能（内部状態を変更しない） | 常時 |

### 計算ロジック

特になし。単純な条件分岐によるポインタ返却のみ。

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

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

該当なし（データベース操作は行わない）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| なし | 未定義動作 | libがNULLの場合 | 呼び出し側で有効なuv_lib_tポインタを保証する必要がある |

### リトライ仕様

リトライは不要。本関数は副作用を持たない読み取り専用関数である。

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

該当なし。

## パフォーマンス要件

O(1)の定数時間で完了する。メモリアロケーションは行わない。

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

- 返却されるエラーメッセージにはファイルパスやシステム情報が含まれる可能性がある
- ユーザー向けに出力する場合はサニタイズを検討すること

## 備考

- Unix系ではerrmsgは `uv__strdup()` で複製されたヒープメモリ
- Windows系ではerrmsgは `FormatMessageA()` の `FORMAT_MESSAGE_ALLOCATE_BUFFER` で確保されたメモリ（`LocalFree` で解放）
- `uv_dlclose()` 呼び出し時にerrmsgメモリは解放される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | unix.h | `include/uv/unix.h` | uv_lib_t構造体の定義（handle, errmsgフィールド） |
| 1-2 | win.h | `include/uv/win.h` | Windows版uv_lib_t構造体の定義（HMODULE handle, char* errmsg） |

**読解のコツ**: uv_lib_tはプラットフォーム依存の型であり、Unix版(L212-215)とWindows版(L314-317)で別々に定義されている。両方ともhandleとerrmsgの2フィールドを持つ点は共通。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | uv.h | `include/uv.h` | uv_dlerror()のAPI宣言 |

**主要処理フロー**:
1. **L1845**: `UV_EXTERN const char* uv_dlerror(const uv_lib_t* lib);` - API宣言。constポインタを受け取りconst char*を返す

#### Step 3: Unix実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | dl.c | `src/unix/dl.c` | uv_dlerror()のUnix実装 |

**主要処理フロー**:
- **60-62行目**: `uv_dlerror()` の実装。errmsgが非NULLならそれを返し、NULLなら "no error" を返す
- **65-80行目**: `uv__dlerror()` 内部関数。POSIXの `dlerror()` を呼び出してエラーメッセージを `uv__strdup()` で複製しlib->errmsgに格納
- **33-38行目**: `uv_dlopen()` 内で `uv__dlerror()` が呼ばれerrmsgが設定される流れ
- **53-57行目**: `uv_dlsym()` 内で `uv__dlerror()` が呼ばれerrmsgが設定される流れ
- **41-50行目**: `uv_dlclose()` 内で `uv__free(lib->errmsg)` によりメモリ解放

#### Step 4: Windows実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | dl.c | `src/win/dl.c` | uv_dlerror()のWindows実装 |

**主要処理フロー**:
- **72-74行目**: `uv_dlerror()` の実装。Unix版と同一のロジック
- **92-135行目**: `uv__dlerror()` 内部関数。`FormatMessageA()` でWindowsシステムエラーメッセージを取得
- **77-88行目**: `uv__format_fallback_error()` - FormatMessage失敗時のフォールバック処理
- **51-62行目**: `uv_dlclose()` 内で `LocalFree()` によりerrmsgメモリ解放

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

```
uv_dlerror(lib)                    [公開API - 読み取り専用]
    └─ lib->errmsg を参照して返却

--- エラーメッセージ設定の流れ ---

uv_dlopen(filename, lib)           [公開API]
    └─ uv__dlerror(lib)            [内部関数]
         ├─ [Unix] dlerror() → uv__strdup()
         └─ [Win]  FormatMessageA()

uv_dlsym(lib, name, ptr)           [公開API]
    └─ uv__dlerror(lib)            [内部関数]

uv_dlclose(lib)                    [公開API]
    └─ errmsgメモリ解放
         ├─ [Unix] uv__free()
         └─ [Win]  LocalFree()
```

### データフロー図

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

uv_lib_t* lib ────▶ uv_dlerror()                 ────▶ const char* エラーメッセージ
                     ├─ errmsg != NULL → errmsg
                     └─ errmsg == NULL → "no error"
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダー | uv_dlerror() API宣言 (L1845) |
| unix.h | `include/uv/unix.h` | ヘッダー | Unix版 uv_lib_t 構造体定義 (L212-215) |
| win.h | `include/uv/win.h` | ヘッダー | Windows版 uv_lib_t 構造体定義 (L314-317) |
| dl.c | `src/unix/dl.c` | ソース | Unix版 uv_dlerror() 実装 (L60-62) |
| dl.c | `src/win/dl.c` | ソース | Windows版 uv_dlerror() 実装 (L72-74) |
| test-dlerror.c | `test/test-dlerror.c` | テスト | uv_dlerror() のテストケース |
