5

ブロック内のnew式は、私のコンピューターで例外をtryスローします。bad_alloc

catch句は、参照ではなく値で例外オブジェクトを受け取ることに注意してください。どうしてe.what()プリントするの"bad allocation"?スライスされると思いました。

#include <iostream>

int main()
{
    try
    {
        int* p = new int[0x1F000000];
    }
    catch(std::exception e)
    {
        std::cout << e.what() << std::endl;
    }
}
4

1 に答える 1

13

Visual Studio(Dinkumware?)はstd::exception、メッセージ用の内部ストレージ†を含む実装を使用します。(文字列を受け入れる非標準のコンストラクターで完了します。)

このため、エラーメッセージを取得するために実際に仮想ディスパッチは必要ありません。スライスしても存続します。

派生オブジェクトが切り取られたため、よりオーソドックスな実装では、実際に一般的な例外メッセージが出力されます。(事実上、MSは同等のものを作成std::exceptionstd::runtime_errorました。の戻り値std::exception::whatは実装定義であるため、これに問題はありませんが、結果を説明します。)


†ここの内部ストレージは大まかに使用されます。内部バッファはありませんが、const char*とがありboolます。はconst char*メッセージ(の戻り値what())を指し、boolはバッファを削除する必要があるかどうかを決定するフラグです。

こんな感じです:

class msvc_exception // for exposition
{
public:
    msvc_exception(const char* msg) :
    mMsg(msg),
    mDoDelete(false)
    {}

    msvc_exception(const std::string& msg) :
    mMsg(copy_string(msg)),
    mDoDelete(true)
    {}

    virtual ~msvc_exception()
    {
        if (mDoDelete)
            delete [] mMsg;
    }

    virtual const char* what() const throw()
    {
        return mMsg ? mMsg : "unknown";
    }

private:
    const char* copy_string(const std::string& str)
    {
        const char* result = new char[str.size() + 1];

        std::copy(str.begin(), str.end(), result);
        result[str.size()] = 0; // null-terminate

        return result;
    }
};

bad_allocこれで、次のように機能することがわかります。

    class msvc_bad_alloc : // for exposition
        public msvc_exception
    {
    public:
        msvc_bad_alloc() :
        msvc_exception("bad_alloc") // note: a static string, no dynamic storage
        {}
    };

メッセージは基本クラスに「存在する」ため、スライスはメッセージに影響を与えません。

GCCやLLVMのような他のコンパイラーは、それをもう少し簡単に実装します。

class orthodox_exception
{
public:
    orthodox_exception(){}
    virtual ~orthodox_exception() {}

    virtual const char* what() const throw()
    {
        return "orthodox_exception";
    }
};

class orthodox_bad_alloc :
    public orthodox_exception
{
public:
    const char* what() const throw()
    {
        return "orthodox_bad_alloc";
    }
};

ここで、スライスはあなたの結果に影響を与えます。(とはいえ、結局のところ、常に参照によってキャッチします。)

于 2011-11-30T23:34:09.213 に答える