Assertion failed の原因と直し方
assert()に渡した条件式がその場でfalseになったときに強制終了するマクロです。「本来ありえないはずの状態」を検出するために使われます。
エラーメッセージの読み方
main: main.c:6: main: Assertion `score > 100' failed.
main: main.c:6: main: Assertion `score > 100' failed.- メモリ管理システム(またはassert)が不整合を検知して出したメッセージ
Aborted- この後プロセスは強制終了します(Aborted)
このエラーが出る典型パターン
パターン1
1 #include <stdio.h> 2 #include <assert.h> 3 4 int main(void) { 5 int score = 85; 6 assert(score > 100 ); ^ 7 printf("score=%d\n", score); 8 return 0; 9 }
assert()は渡した条件式がその場でfalseになると強制終了します。scoreは85で100を超えていないのに「100より大きいはず」と誤った前提を書いてしまうと、プログラマ自身のロジックミスとして検出されます。
直し方: score > 100 を score <= 100 にします。
パターン2
1 #include <stdio.h> 2 #include <assert.h> 3 4 int main(void) { 5 int stock = 0; 6 assert(stock > 0 ); ^ 7 printf("stock=%d\n", stock); 8 return 0; 9 }
在庫が0であること自体は正常なケースかもしれません。「0はありえない」という誤った前提のassertを書くと、正常な状態でも強制終了してしまいます。
直し方: stock > 0 を stock >= 0 にします。
パターン3
1 #include <stdio.h> 2 #include <assert.h> 3 4 int main(void) { 5 int temp = 36; 6 assert(temp < 0 ); ^ 7 printf("temp=%d\n", temp); 8 return 0; 9 }
assertは「本来ありえないはずの状態」を検出するためのものです。前提そのものを書き間違えると、正常な値でも強制終了の原因になります。
直し方: temp < 0 を temp >= 0 にします。
パターン4
1 #include <stdio.h> 2 #include <assert.h> 3 4 int main(void) { 5 int age = 25; 6 assert(age > 150 ); ^ 7 printf("age=%d\n", age); 8 return 0; 9 }
25は150を超えていないのに「150より大きいはず」という誤った前提を書くと、正常な値でも強制終了します。
直し方: age > 150 を age <= 150 にします。
パターン5
1 #include <stdio.h> 2 #include <assert.h> 3 4 int main(void) { 5 int count = 0; 6 assert(count != 0); ^ 7 printf("count=%d\n", count); 8 return 0; 9 }
countが0であること自体は正常な場合もあります。「0はありえない」という誤った前提のassertは正常な状態でも落ちます。
直し方: count != 0 を count >= 0 にします。
よくある誤解
assertはエラーハンドリングの代わりではありません。ユーザー入力のような「起こりうる」異常はif文で処理すべきで、assertは「プログラマのロジックの前提が崩れていないか」を検査するための開発時のツールです。NDEBUGを定義してビルドすると、assertはまるごと消え去ることにも注意が必要です。
実務での勘所
assertを使うべき場面と、if文とエラー処理を書くべき場面は明確に分かれます。assertは「ここに来た時点でこの条件は絶対に成り立っているはず(成り立っていなければプログラマのバグ)」を検査するためのもので、NDEBUGを定義したリリースビルドでは丸ごと消えます。一方、ユーザー入力やファイルの読み込み失敗のように、正しいプログラムでも実際に起こりうる異常はassertではなくif文で検査し、リリースビルドでも必ず動くエラー処理を書く必要があります。