2010-03-07 2 views
1

Я работаю над графическим приложением. Он значительно использует виртуальные классы. Я получаю некоторые ошибки сегментации, которые у меня возникают при отладке.Ошибки сегментации виртуальных классов

начальных классах в этом приложении:

  • Shape (виртуальный класс)
    • Прямоугольник
    • Polygon
    • Круг
  • Picture (в основном коллекция формы)

Вот сокращенная копия соответствующей части моего кода:

class Picture 
{ 
    ... 
    Picture(Graphics& gd) 
    { 
    gfx = &gd; 
    } 

    void Picture::draw() const 
    { 
    for(int i=0; i<shapes.size();i++) 
    { 
     shapes[i]->draw(*gfx); // This line causes a segmentation fault 
    } 
    } 
... 
private: 
    std::vector<Shape*> shapes; 
    Graphics* gfx; 
} 

class Shape 
{ 
... 
virtual void draw(Graphics& g) const = 0; 
... 
} 

Вот сеанса GDB показывает некоторую информацию:

 
Program terminated with signal 11, Segmentation fault. 
[New process 89330 ] 
#0 0x00020d38 in Rectangle::draw (this=0x41e10, [email protected]) 
    at rectangle.cpp:42 
42   g.setColor(getFillColor()); 
(gdb) print &g 
$1 = (class Graphics *) 0xffbff904 
(gdb) bt 
#0 0x00020d38 in Rectangle::draw (this=0x41e10, [email protected]) 
    at rectangle.cpp:42 
#1 0x0001bae8 in Picture::draw (this=0xffbff950) at picture.cpp:45 
#2 0x0002394c in writePicture (p= 
     { = {_vptr.Figure = 0x2be38}, shapes = { >> = {_M_impl = {> = {> = {}, }, _M_start = 0x3f648, _M_finish = 0x3f664, _M_end_of_storage = 0x3f664}}, }, gfx = 0xffbff904}, fileName= 
     {static npos = 4294967295, _M_dataplus = {> = {> = {}, }, _M_p = 0x3f49c "t1.dat.eps"}}) at testpicture.cpp:51 
#3 0x00023b3c in simpleTest (inFileName= 
     {static npos = 4294967295, _M_dataplus = {> = {> = {}, }, _M_p = 0x3fe24 "t1.dat"}}, outFileName= 
     {static npos = 4294967295, _M_dataplus = {> = {> = {}, }, _M_p = 0x3f49c "t1.dat.eps"}}, [email protected]) at testpicture.cpp:70 
#4 0x00024c3c in main (argc=2, argv=0xffbffa74) at testpicture.cpp:165

Я стучал головой о стену на пару часов, пытаясь понять эту штуку. Это как-то связано с членом Graphic класса Picture. Тем не менее, я не вижу, как он объединяется, чтобы создать ошибку сегментации.

EDIT:

Вот часть testpicture.cpp, где создается объект графика:

RectangularArea getPictureBounds (string fileName) 
{ 
    ifstream in (fileName.c_str()); 

    PSGraphics gr(fileName + ".bb"); 
    Picture p0(gr); 

    Shape* shape; 
    while (in >> shape) 
    { 
    if (shape != NULL) 
     p0.add(*shape); 
    } 
    return p0.boundingBox(); 
} 

Graphic представляет собой виртуальный класс, а также. В этом случае PSGraphic наследует от него.

+0

Можете ли вы опубликовать 'testpicture.cpp' - похоже, проблема там. Как выделяется экземпляр «Graphics»? –

+0

Можно указать по адресу, что он выделен из стека (автохранилище). – Tronic

+0

Да, это очевидно. Вопросы, надеюсь, заставят OP смотреть на другие части кода с подозрением. –

ответ

2

gfx указывает на объект в стеке. Вы уверены, что объект все еще там (в том же месте, где он был), когда вы пытаетесь нарисовать?

+0

Это хороший момент. Как я могу поместить этот объект в кучу, поскольку функция clone() недоступна? –

+0

Выделите его оператором new или поместите его внутри некоторого объекта, который выделен из кучи. – Tronic

2

Неправильная практика хранения указателя на аргумент, предоставленный вам в качестве ссылки - это создает путаницу в отношении памяти . Либо сделайте копию объекта, на который ссылается (если это значение класс), либо измените метод на использование смарт-указателя (например, boost::shared_ptr) на общий ресурс. Таким образом, управление ресурсами является явным.

К вашему немедленному выпуску - экземпляр Graphics, вероятно, выделен в стеке и выходит за пределы области действия, таким образом, разрушен. Тогда ваш код Picture ссылается на мертвый объект.

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