C++ 実行時エラー辞典 — よく出る 16 種
コンパイルが通っても実行中に落ちる。その多くは未定義動作 (UB) かライブラリの例外です。典型パターンを見て慣れれば、再発生時に数秒で「ああ、これ」と気付けるようになります。
すべて
メモリ
ライブラリ例外
並行
数値
memR01. SEGV — ヌルポインタ参照
Segmentation fault (core dumped)
原因: nullptr を -> / * で辿った。実行時ログに出ないので、gdb で bt するのが王道。
ng.cppUB
Widget* p = nullptr;
p->show(); // SEGV
ok.cppOK
if (p) p->show();
// 所有したいなら std::unique_ptr
検出: gdb / ASan
memR02. SEGV — ダングリングポインタ
原因: 解放済みメモリ / スコープ外のローカル変数を参照。
ng.cppUB
int* bad() {
int x = 5;
return &x; // スコープ外
}
ok.cppOK
int good() { return 5; }
// または shared_ptr で寿命共有
検出: AddressSanitizer
memR03. ヒープバッファオーバーラン
原因: 確保したサイズを越える書き込み。C の strcpy や C++ でも new int[10] に 10 番目を書く等。vector::at や vector 自体への置き換えが根本策。
ng.cppUB
int* a = new int[5];
a[5] = 0; // 1 個はみ出し
ok.cppOK
std::vector<int> a(5);
a.at(5); // out_of_range を投げる
検出: ASan
memR04. use-after-free
原因: delete 後のポインタにアクセス。iterator 無効化もこのカテゴリ。
検出: ASan
memR05. double free
原因: 同じポインタを 2 回 delete。unique_ptr / shared_ptr でほぼ消せる。
検出: ASan / glibc の runtime check
memR06. iterator 無効化クラッシュ
原因: vector::push_back で再配置が起きると既存イテレータは全て無効。無効なイテレータを * すると未定義。
ng.cppUB
auto it = v.begin();
v.push_back(9); // 再配置で it 無効
*it; // UB
ok.cppOK
v.reserve(100); // 先に予約
auto it = v.begin();
v.push_back(9);
検出: libstdc++ の _GLIBCXX_DEBUG
libR07. std::bad_alloc
terminate called after throwing an instance of 'std::bad_alloc'
原因: new がメモリ確保に失敗。32-bit 環境や組込で出やすい。サイズを確認するか、new (std::nothrow) で nullptr 戻り値を選ぶ。
libR08. std::out_of_range(at / substr)
terminate called: std::out_of_range: vector::_M_range_check
原因: at(i) が範囲外。operator[] は未定義(ASan 推奨)。
libR09. std::bad_optional_access
terminate called: std::bad_optional_access
原因: 空の optional に .value()。value_or() か事前 if 判定。
libR10. std::bad_variant_access
原因: variant の現在の型と違う型で get<T>。holds_alternative か visit を使う。
libR11. std::terminate() 呼び出し
原因: 捕まえられない例外 / デストラクタから例外 / noexcept 関数が投げた / std::thread 未 join。バックトレースで直上の throw を探す。
thR12. データ競合によるデータ破壊
原因: 複数スレッドが同じ変数を読み書き。値がじわじわおかしくなる(再現性低)。ThreadSanitizer(-fsanitize=thread)で検出。
検出: TSan
thR13. デッドロック(ハング)
原因: 循環するロック順序。std::scoped_lock を使うか、プロセス全体でロック順を統一する。
検出: TSan / gdb info threads
numR14. 整数オーバーフロー(signed)
原因: signed int の最大値を超えると UB(unsigned はラップ)。-fsanitize=undefined で検出できる。std::clamp / __builtin_add_overflow で安全に。
検出: UBSan
numR15. ゼロ除算
原因: 整数の x / 0 は UB。浮動小数の 0.0/0.0 は NaN(これは UB ではない)。
検出: UBSan
memR16. stack overflow(再帰深すぎ)
原因: 無限再帰 or 巨大配列をスタックに。スタック上のサイズ上限は通常 1〜8 MB。巨大配列は std::vector へ。