Ошибка Segfault при создании smartpointer в CairoContext

#c #segmentation-fault #cairo #gtkmm

#c #ошибка сегментации #cairo #gtkmm

Вопрос:

У меня возникли некоторые проблемы при создании Cairo::RefPtr в контексте Cairo. Я действительно не могу себе представить, почему это ошибка segfaults, за исключением того, что указатель указывает на что-то совершенно неправильное.

Это мой код.

 int main(int argc, char * argv[])
    {
    Gtk::Main kit(argc, argv);
    Gtk::Window window;
    Gtk::DrawingArea drawarea;
    window.add(drawarea);
    Cairo::RefPtr<Cairo::Context> ccontext = drawarea.get_window()->create_cairo_context();
    Gtk::Allocation allocation = drawarea.get_allocation();
    const int width = allocation.get_width();
    const int height = allocation.get_height();
    ccontext->set_source_rgb(1.0, 0.0, 0.0);
    ccontext->set_line_width(2.0);
    ccontext->move_to(0,0);
    ccontext->line_to(width, height);

    Gtk::Main::run(window);

    }
  

И это то, что говорит GDB:

Запуск программы: /home/marian/Desktop/C /Langton/Langton [Включена отладка потоков с использованием libthread_db]

Программа получила сигнал SIGSEGV, ошибка сегментации. 0xb7be852e в Gdk::Window::create_cairo_context() () из /usr/lib/libgdkmm-3.0.so.1

Я скомпилировал это с помощью gcc (GCC) 4.6.1 20110819 (предварительная версия).

Заранее спасибо

Комментарии:

1. Возможно, мне следует предоставить больше информации. Это более или менее напрямую из ссылки gtkmm, код должен быть правильным. Я скомпилировал его с помощью: g main.cc -g -o Langton pkg-config —cflags —libs cairomm-1.0 gtkmm-3.0` ` Это было скомпилировано в Arch Linux с установленным Gtkmm3.2.0-1 и Cairomm-1.10.0-1

Ответ №1:

Gtk::Widget::get_window() возвращает нулевое значение Glib::RefPtr, поскольку виджет еще не реализован.

Основываясь на документации GtkDrawingArea, вам необходимо подключить сигнал «рисовать» для обработки рисования, где ваш контекст Cairo уже создан и передан вам. Возвращаясь к ссылке Gtkmm, вы должны использовать Gtk::Widget::signal_draw(), чтобы подключиться к ней, или вы можете перегрузить виртуальную функцию on_draw() для обработки вашего чертежа.

Кроме того, вам также необходимо вызвать .show() для каждого виджета, то есть для вашей области рисования и вашего окна, и вызвать ccontext-> stroke(), чтобы получить фактически нарисованную линию.

Результат будет выглядеть примерно так:

 #include <gtkmm.h>

bool draw (const Cairo::RefPtr<Cairo::Context> amp;ccontext, Gtk::DrawingArea *drawarea)
{
    Gtk::Allocation allocation = drawarea->get_allocation();
    const int width = allocation.get_width();
    const int height = allocation.get_height();
    ccontext->set_source_rgb(1.0, 0.0, 0.0);
    ccontext->set_line_width(2.0);
    ccontext->move_to(0,0);
    ccontext->line_to(width, height);
    ccontext->stroke ();

    return true;
}

int main(int argc, char * argv[])
{
    Gtk::Main kit(argc, argv);
    Gtk::Window window;
    Gtk::DrawingArea drawarea;

    drawarea.signal_draw ().connect (sigc::bind (sigc::ptr_fun (amp;draw),
                                                 amp;drawarea));
    window.add(drawarea);
    window.show_all ();

    Gtk::Main::run(window);
    return 0;
}
  

или в качестве альтернативы:

 #include <gtkmm.h>

class LineBox : public Gtk::DrawingArea
{
protected:
    virtual bool on_draw (const Cairo::RefPtr<Cairo::Context> amp;ccontext);
};

bool LineBox::on_draw (const Cairo::RefPtr<Cairo::Context> amp;ccontext)
{
    Gtk::Allocation allocation = get_allocation();
    const int width = allocation.get_width();
    const int height = allocation.get_height();
    ccontext->set_source_rgb(1.0, 0.0, 0.0);
    ccontext->set_line_width(2.0);
    ccontext->move_to(0,0);
    ccontext->line_to(width, height);
    ccontext->stroke ();

    return true;
}

int main(int argc, char * argv[])
{
    Gtk::Main kit(argc, argv);
    Gtk::Window window;
    LineBox drawarea;

    window.add(drawarea);
    window.show_all ();

    Gtk::Main::run(window);
    return 0;
}