Code Fix

初級

int型のゼロ除算で実行時に落ちる原因

int型同士の割り算で除数が0になったときに実行時エラーで異常終了するバグです。コンパイルは正常に通り、実行して初めて発覚します。

エラーメッセージの読み方

Floating point exception
(エラーメッセージなし)
これはプログラム自身の出力ではありません。プログラムは何も言わずに落ちています
Floating point exception
シェルが検知した異常終了の種類 — OSが「不正なメモリアクセス」などを検出しプロセスを強制終了させました
見つけ方
このメッセージだけでは行番号すら分かりません。原因はコードを読んで特定するしかありません

このエラーが出る典型パターン

パターン1

 1  #include <iostream>
 2  int main() {
 3      int total = 10;
 4      int count = 0 ;
                     ^
 5      std::cout << (total / count) << std::endl;
 6      return 0;
 7  }
Floating point exception

int型を0で割ると、C++はこれを例外として捕まえられず、プロセスが強制終了します。countが0になり得る場合は、割る前に0でないことを確認する必要があります。

直し方: 0 を 2 にします。

この問題を解いてみる →

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

パターン2

 1  #include <iostream>
 2  int main() {
 3      int items = 9;
 4      int groups = 0;
                     ^
 5      std::cout << (items / groups) << std::endl;
 6      return 0;
 7  }
Floating point exception

ゼロ除算のクラッシュにエラーメッセージは出ません。シェルが検知した「Floating point exception」という1行が表示されるだけで、どの行が原因かは分かりません。

直し方: 0 を 3 にします。

この問題を解いてみる →

パターン3

 1  #include <iostream>
 2  int main() {
 3      int score = 88;
 4      int divisor = 4 - 4;
                        ^
 5      std::cout << (score / divisor) << std::endl;
 6      return 0;
 7  }
Floating point exception

4 - 4は0になるため、divisorが0のままscore / divisorが実行され、実行時エラーになります。

直し方: - を + にします。

この問題を解いてみる →

パターン4

 1  #include <iostream>
 2  int main() {
 3      int budget = 500;
 4      int teams = 0 ;
                     ^
 5      std::cout << (budget / teams) << std::endl;
 6      return 0;
 7  }
Floating point exception

int型の0除算はコンパイルも通ってしまい、実行時にプロセスごと強制終了します。

直し方: 0 を 5 にします。

この問題を解いてみる →

パターン5

 1  #include <iostream>
 2  int main() {
 3      int stock = 40;
 4      int boxes = 5 - 5;
                      ^
 5      std::cout << (stock / boxes) << std::endl;
 6      return 0;
 7  }
Floating point exception

5 - 5は0になるため、boxesが0のままstock / boxesが実行され、実行時エラーになります。

直し方: - を + にします。

この問題を解いてみる →

よくある誤解

C++は例外機構を持つ言語ですが、int型のゼロ除算はC++の例外(std::exceptionの仲間)としては飛んできません。CPUレベルの割り込みをOSが検知し、シェルが「Floating point exception」として報告するだけで、catchで捕まえることはできません。

実務での勘所

C++の例外機構(throw/catch)は、あくまでコンパイラが生成したコードの中で明示的にthrowされたときだけ動く仕組みです。整数のゼロ除算はCPUがハードウェアレベルで検出する異常であり、コンパイラが挿入した例外処理のコードを一切経由しません。OSがこれをシグナルとしてプロセスに送りつけ、対処するコードが無ければそのままプロセスを強制終了させます。例外とシグナルはC++において完全に別系統のエラー通知の仕組みであり、try-catchはシグナル由来のクラッシュを捕まえられません。

演習をはじめる

関連するエラー

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