2016-03-26 3 views
-1

У меня есть код, который работает нормально, но он прерывается, когда я добавляю обработку исключений. Я новичок, и вот кодпрограмма неожиданно прекращается после ввода блока catch

Этот код работает (для краткости, включают защитные ограждения не показаны):

В 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(const std::string &label) : _label(label) { 
    for (auto i : getUniverse()) { 
      if ((*getUniverse().find(i))->label() == _label) throw DuplicateObj; 
    } 
    getUniverse().insert(this); 
} 

и закомментируйте экземпляр дубликата плоскости в основном (чтобы избежать запуска броска). Он компилируется и запускается без проблем.

тогда я обернуть объект Инстанцирование строки в Try/поймать блок в основном:

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. 
+0

Вам не нужен частный конструктор по умолчанию. Когда вы укажете другой конструктор, по умолчанию будет подавлено. –

+1

Я не вижу код, в котором вы выбрали исключение. –

+0

В идеале, отправьте что-то полное и компилируемое. – kec

ответ

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 содержит указатель на уничтоженный объект.

Crash!

p.s .: извините за мой плохой английский.

+0

Это как раз проблема! Я понял, что проблема связана с объемом, но я не мог понять, что именно. В точку! Большое спасибо! Есть ли способ избежать этого, кроме объявления P с кучи? @ max66 –

+0

Я не знаю, есть ли другие способы. Просто имейте в виду, что 'universe' использует указатели, поэтому вы должны убедиться, что эти указатели действительны. В этом случае вы можете использовать 'new' /' delete' или вы можете использовать 'printworld' внутри блока' try' – max66

Смежные вопросы