程序段引入后,程序意外终止

时间:2016-03-26 17:40:50

标签: c++ exception

我有一段正常运行的代码,但是当我添加异常处理时它会中断。我是初学者,这里是代码

此代码有效(为简洁起见,不包括警卫):

在plane.h中:

#include "vector.h" //which, like point.h, inherits from orderedpair.h
class Plane {
    public:
        Plane(const std::string &label);
        Plane(const Plane &);
        virtual ~Plane();

        void insert(const OrderedPair &);
        void label(const std::string & label);
        std::string label() const {return _label;}

    protected:
        std::string _label;
        bool operator==(const Plane &rhs) const {return label() == rhs.label();}
        bool operator<(const Plane & rhs) const {return label() < rhs.label();}
};

在plane.cpp中

#include <set>
Plane::Plane(const std::string &label) : _label(label) {
     getUniverse().insert(this);
}

/*GLOBAL OBJECTS*/

extern std::set<Plane *>& getUniverse() {
    static std::set<Plane *>universe;
    return universe;
}

extern Plane& getDefaultPlane() {
    static Plane Default("Default");
    return Default;
}

void printworld() {
    for (auto i : getUniverse())
        std::cout << (*getUniverse().find(i))->label() << std::endl;
}

并在主要:

//MinGW32 4.9 Code::Blocks 16.01 Windows Vista(!!) 64bit -std=C++11
#include <iostream>
#include "vector.h" //includes point.h which includes orderedpair.h
#include "plane.h"

using namespace std;

namespace {
    struct Initializer {;
        Initializer();
    };
}

int main() {

static Initializer init;
Point A("A", 1, 1);

Plane P("P");
Plane duplicate("Default");

printworld();
return 0;
}

Initializer::Initializer()
{
   // Trigger construction of the default Plane
   getDefaultPlane();
}

然后我在plane.h中包含异常并在顶部添加以下内容:

class E : public std::exception {
    const char *msg = nullptr;
public:
    E(const char *m) throw() : msg(m) {}
    const char *what() const throw() {return msg;}
};
const E DuplicateObj("Object already exists!\n");

它编译并运行,没有问题。 然后我以这种方式更改Plane的构造函数(以确保之前没有使用过标签):

Plane::Plane(const std::string &label) : _label(label) {
     for (auto i : getUniverse()) {
           if ((*getUniverse().find(i))->label() == _label) throw DuplicateObj;
     }
    getUniverse().insert(this);
}

并注释掉main中重复平面的实例化(以避免触发throw)。它编译并运行,没问题。

然后我将对象实例化行包装在main中的try / catch块中:

try {
    Point A("A", 1, 1);
    Plane P("P");
    //Plane duplicate("Default");
}
catch (const E& e) {
    cerr << e.what() << endl;
}
catch (const exception &e) {
    cerr << e.what() << endl;
}

它编译但崩溃,结果如下:

Process returned -1073741819 (0xC0000005)   execution time : 9.537 s
Press any key to continue.

1 个答案:

答案 0 :(得分:0)

不是异常问题。

这是指针和范围的问题。

如果我没错。

您的Plane构造函数插入(getUniverse().insert(this);this指针位于静态全局集(static std::set<Plane *>universe;中的getUniverse())。

然后,您在main()printworld())的最后一条指令中使用该全局集。

在引入try / catch块之前,Plane P("P");对象的范围是完整的main()函数;因此,当您调用P时,指向printworld的指针是一个有效指针。

但是当你写作

try {
    Plane P("P");
    // end of P scope
 }

// P is out of scope; the pointer to P, in universe, is invalid

printworld(); // use of a invalid pointer to P

P的范围仅为try块;因此,当您从printworld()块中调用try时,universe包含指向已销毁对象的指针。

崩溃!

p.s:抱歉我的英语不好。