Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么'e.what()'prints';“错误分配”;?_C++_Visual Studio 2008_Exception Handling_Object Slicing - Fatal编程技术网

C++ 为什么'e.what()'prints';“错误分配”;?

C++ 为什么'e.what()'prints';“错误分配”;?,c++,visual-studio-2008,exception-handling,object-slicing,C++,Visual Studio 2008,Exception Handling,Object Slicing,try块中的new表达式在我的计算机中引发bad\u alloc异常 请注意,catch子句通过值而不是引用接收异常对象。为什么e.what()打印“错误分配”?我以为它会被切成薄片 #include <iostream> int main() { try { int* p = new int[0x1F000000]; } catch(std::exception e) { std::cout <<

try
块中的
new
表达式在我的计算机中引发
bad\u alloc
异常

请注意,catch子句通过值而不是引用接收异常对象。为什么
e.what()
打印
“错误分配”
?我以为它会被切成薄片

#include <iostream>

int main()
{
    try
    {
        int* p = new int[0x1F000000];
    }
    catch(std::exception e)
    {
        std::cout << e.what() << std::endl;
    }
}
#包括
int main()
{
尝试
{
int*p=新的int[0x1F000000];
}
捕获(标准::异常e)
{
std::coutVisual Studio(Dinkumware?)使用包含消息内部存储†的
std::exception
实现。(使用接受字符串的非标准构造函数完成。)

因此,实际上不需要虚拟调度来获取错误消息,它可以经受任何切片

更正统的实现确实会打印一条通用异常消息,因为派生对象被切掉了。(实际上,MS已经使
std::exception
std::runtime\u 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;
    }
};
    class msvc_bad_alloc : // for exposition
        public msvc_exception
    {
    public:
        msvc_bad_alloc() :
        msvc_exception("bad_alloc") // note: a static string, no dynamic storage
        {}
    };
现在您可以看到
bad\u alloc
的工作原理如下:

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

在这里,切片将影响您的结果(也就是说,毕竟:始终通过引用捕获)

你刚刚试着在你的程序中分配=~1.9375GB。你是在编译32位吗?你的机器中有这么多RAM吗?@GMan编译器是MS VS 2008,所以你是说
异常
为所有派生类保留字符串的副本?我要祝贺你的出色解释。我是贝吉所以我花了一段时间才完全理解它。