1. ホーム
  2. c++

[解決済み] C++の例外処理 'char const*'のインスタンスを投げた後に呼び出される Terminate

2022-03-04 01:35:07

質問

エラー: char const*' のインスタンスを投げた後に Terminate が呼び出されました。

アプリケーションを終了させるために、ランタイムが異常な方法でアプリケーションを終了させることを要求しています。アプリケーションのサポートチームに連絡してください。

これをやるとコンパイラがクラッシュする原因がよくわからないのです。何か思い当たることはありますか?プログラミングは少し初めてです。

#include <iostream>
#include <iomanip>

using namespace std;

//Template for Maximum

template <class X>
X Maximum(X arg1, X arg2)
{
    if (arg1 > arg2)
        return arg1;
    else
        return arg2;
}

//Template for Minimum

template <class M>
M Minimum(M arg1, M arg2)
{
    if (arg1 > arg2)
        return arg2;
    else
        return arg1;
}

/* Template for Divide(D arg1, D arg2) arg1: the dividend arg2: the divisor Description: 
Divides arg1 by arg2. If arg2 equals zero then an exception is thrown. */

template <class D>
D Divide(D arg1, D arg2)
{
    if (arg2 == 0) {
        throw "You cannot devide by zero! ";
    }
    return (arg1 / arg2);
}

int main()
{

    int a, b;
    float c, d;
    double e, f;
    a = 2;
    b = 22;
    cout << setprecision(4) << fixed << showpoint << "min:" << Minimum(a, b) << "\tmax: " << Maximum(a, b) << endl;
    c = 4.7f;
    d = 2.97f;
    cout << setprecision(4) << fixed << showpoint << "min:" << Minimum(c, d) << "\tmax: " << Maximum(c, d) << endl;

    e = 387.78;
    f = 387.7798;
    cout << setprecision(4) << fixed << showpoint << "min:" << Minimum(e, f) << "\tmax: " << Maximum(e, f) << endl;
    e = 40;
    f = 0;
    try {
        cout << setprecision(4) << fixed << showpoint << "Divide: " << e << '/' << f << " = " << Divide(e, f) << endl;
    }
    catch (string exceptionString) {
        cout << exceptionString;
    }
    system("pause");
    return 0;
}

解決方法は?

文字列リテラルは std::string . 前者を投げておきながら、後者を捕まえようとする。にもかかわらず std::string は文字列リテラルから構築されるかもしれませんが、catch節では起こりません。catch節で許可される変換は、次のセクションで詳しく説明されています。 [except.ハンドル]/3 :

ハンドラは、以下の場合、タイプEの例外オブジェクトにマッチします。

  • ハンドラの型が cv T または cv T& で,E と T が同じ型(トップレベルの cv-qualifiers は無視)である,あるいは
  • ハンドラが cv T または cv T& 型であり,T が E の曖昧でないパブリックな基底クラスである場合,または
  • ハンドラが cv T または const T& 型である場合,T はポインタまたはメンバ型へのポインタ,E はポインタまたはメンバ型へのポインタである. のうちの1つ以上によってTに変換できるものである。
    • private、protected、曖昧なクラスへのポインタへの変換を伴わない標準的なポインタ変換。
    • 関数ポインタ変換
    • 資格変換、または
  • ハンドラが cv T または const T& 型である場合,T はポインタまたはメンバ型へのポインタ,E は std::nullptr_t である。

また、リテラル->の場合はどちらも適用されませんでした。 std::string の変換を行います。

その結果、最終的にその例外はキャッチされず、ランタイムが std::terminate キャッチされない例外が発生した場合に想定されるように。

一般的には、専用の例外型(階層の一部かもしれません)を投げ、その型名が発生したエラーを伝えるようにするのがベストでしょう。これにより、ハンドラ(またはハンドラのセット)を書く必要がある場合、より堅牢な方法でエラーを処理することができます。

もし、何らかの理由で標準的なやり方に従いたくない場合は、上記の箇条書きで述べたような変換をしなければなりません。どちらかにすることができます。

  1. を投げる。 std::string リテラル のように "You cannot devide by zero!"s (ただし s という接尾辞があります)。
  2. をキャッチする const char* .