Code Fix

上級

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  }
main: main.c:6: main: Assertion `score > 100' failed. Aborted

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  }
main: main.c:6: main: Assertion `stock > 0' failed. Aborted

在庫が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  }
main: main.c:6: main: Assertion `temp < 0' failed. Aborted

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  }
main: main.c:6: main: Assertion `age > 150' failed. Aborted

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  }
main: main.c:6: main: Assertion `count != 0' failed. Aborted

countが0であること自体は正常な場合もあります。「0はありえない」という誤った前提のassertは正常な状態でも落ちます。

直し方: count != 0 を count >= 0 にします。

この問題を解いてみる →

よくある誤解

assertはエラーハンドリングの代わりではありません。ユーザー入力のような「起こりうる」異常はif文で処理すべきで、assertは「プログラマのロジックの前提が崩れていないか」を検査するための開発時のツールです。NDEBUGを定義してビルドすると、assertはまるごと消え去ることにも注意が必要です。

実務での勘所

assertを使うべき場面と、if文とエラー処理を書くべき場面は明確に分かれます。assertは「ここに来た時点でこの条件は絶対に成り立っているはず(成り立っていなければプログラマのバグ)」を検査するためのもので、NDEBUGを定義したリリースビルドでは丸ごと消えます。一方、ユーザー入力やファイルの読み込み失敗のように、正しいプログラムでも実際に起こりうる異常はassertではなくif文で検査し、リリースビルドでも必ず動くエラー処理を書く必要があります。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)