Domanda

L'espressione new nel blocco try getta un bad_allocexception nel mio computer.

Si noti che la clausola catch riceve un oggetto eccezione per valore, non per riferimento. Come mai le stampe e.what() "bad allocation"? Ho pensato che sarebbe essere affettato.

#include <iostream>

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

Soluzione

Visual Studio (Dinkumware?) Utilizza un'implementazione di std::exception che contiene memoria interna † per il messaggio. (Completo di un costruttore non standard che accetta una stringa.)

A causa di questo, non la spedizione virtuale è effettivamente necessario per ottenere il messaggio di errore, sopravvive alcun taglio.

Un'implementazione più ortodosso sarebbe davvero stampare un messaggio di eccezione generica, perché l'oggetto derivato è stata tagliata fuori. (In effetti, MS ha fatto std::exception e std::runtime_error equivalente. Non c'è niente di sbagliato in questo, dal momento che il valore di ritorno di std::exception::what è definito dall'implementazione, ma spiega i risultati.)


† Memoria interna qui è usato impropriamente. Essa non ha un interno di buffer , ma ha un const char* e bool. I punti const char* al messaggio (il valore di ritorno di what()), e il bool è una bandiera determinare se il buffer deve essere eliminato.

E 'in questo modo:

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;
    }
};

Vedete ora che funziona bad_alloc come questo:

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

affettare non influenza il messaggio perché il messaggio "esiste" nella classe base.

Altri compilatori, come GCC e LLVM, implementare un po 'più dritto in avanti:

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";
    }
};

Qui, affettare interesserebbe il vostro risultato. (Detto questo, dopo tutto questo:. Sempre prendere per riferimento)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top