✅発生したエラーとその意味
terminate called after throwing an instance of 'std::invalid_argument'
what(): 0より大きい数値を入力してください。
run: line 1: 3 Aborted (core dumped) LD_LIBRARY_PATH=/usr/local/gcc-9.2.0/lib64 ./a.out
terminate called after throwing an instance of 'std::invalid_argument'
→ std::invalid_argument
型の例外が投げられた(throwされた)あとに、terminate()
が呼ばれて異常終了したことを示している。
-
what(): 0より大きい数値を入力してください。
→
throw
時に渡したメッセージ(what()
の中身)が表示されている。つまり、例外オブジェクトがなぜエラーなのかを伝えてくれている部分。
-
Aborted (core dumped)
→ 例外が捕まえられなかった(catchされなかった)ため、プログラムがクラッシュ(Abort)して、メモリダンプが出力されたことを示している。
⚠️ 原因
以下のコード内でthrow
によって例外(std::invalid_argument
)が投げられているが、main()
関数内でtry-catch
による処理がされていなかったため、プログラムが例外未処理のまま異常終了した。
if (val <= 0) {
throw std::invalid_argument("0より大きい数値を入力してください。");
}
🛠 解決策
- 大前提:例外を投げたら必ずどこかで受け取って処理すること。
- 例外が発生する可能性のある関数を呼び出す時は、
try-catch
文で囲んで例外を適切に処理すること。 - これにより、プログラムのクラッシュが防ぎ、ユーザーに適切なエラーメッセージを提示できる。
- また、
what()
を使えば、例外の詳細なメッセージを取得可能。
✅修正後のコード例
#include <iostream>
#include <string>
#include <stdexcept>
std::string convertVal (int val, std::string type) {
std::string result;
int divisor;
// 例外処理
if (val <= 0) {
throw std::invalid_argument("0より大きい数値を入力してください。");
}
// 16進数に変換する場合
if (type == "hex") {
divisor = 16;
// 2進数に変換する場合
} else if (type == "bits") {
divisor = 2;
}
// 以下で余りを16進数や2進数に変換していく
while (val > 0) {
int remaind = val % divisor;
if (type == "hex" && remaind >= 10) {
int diff = remaind - 10;
char hex = 'A';
hex += diff;
result = hex + result;
} else {
result = std::to_string(remaind) + result;
}
val /= divisor;
}
return result;
}
int main () {
try {
std::cout << convertVal(0, "bits") << std::endl;
} catch (const std::invalid_argument& e) {
std::cerr << "入力エラー" << e.what() << std::endl;
return 1;
}
return 0;
}
💡補足
-
catch
ではconst std::invalid_argument& e
のように「const参照」で受け取ることで、無駄なコピーを避けつつ安全に例外メッセージを参照できる。 - そもそもエラーとは、プログラムが正常に動かない状況全般のこと。その中で、意図的に throw できて、try-catch で対応できるものを「例外」と呼ぶ。
- Pythonのようなインタプリタ言語は、例外を自動で発生させてくれる場面が多いが、C++のようなコンパイル言語では、開発者が自分で throw して例外処理を書く必要がある。
- 例外処理の目的は、プログラムのクラッシュを未然に防いだり、安全に終了したり、代替処理を入れたりするため。