2013-05-29 3 views
1

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

void drawCircle(cairo_surface_t *container, int x, int y, int radius, float r, float g, float b, float a) 
{ 
cairo_t *cairoInstance;                              
cairoInstance = cairo_create(container);                              

cairo_set_source_rgba(cairoInstance, r, g, b, a); 
cairo_arc(cairoInstance, x, y, radius, 0, 2*M_PI); 
cairo_stroke_preserve(cairoInstance); 
cairo_fill_preserve(cairoInstance); 

//delete cairoInstance; 
gtk_widget_queue_draw_area(GTK_WIDGET(frame2), 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); 
} 

Любые идеи? Спасибо заранее.

+0

использование Valgrind для определения происхождения утечек памяти –

ответ

2

Несколько моментов:

  • cairo_t s являются подсчет ссылок. Позвоните по телефону cairo_destroy, когда закончите с cairo_t*. В качестве альтернативы вам не нужно создавать и уничтожать cairo_t для каждого круга - реорганизовать функцию, вытащив вызов до cairo_create.
  • Если вам это не нужно, предпочитайте cairo_X функции cairo_X_preserve. В вашем коде cairo_fill_preserve должно быть cairo_preserve. (Интенсивность должна быть сохранена, поэтому, чтобы выполнялась следующая заливка.)
  • Вызов аннулирования прямоугольника вашего виджета gtk с помощью gtk_widget_queue_draw_area также может быть реорганизован и выполнен только один раз за ничью.
  • gtk_widget_queue_draw_area аннулирует прямоугольную область окна виджетов - вы можете быть хорошо только с gdk_window_invalidate_rect - см the documentation

псевдопользователей-код после рефакторинга (с гипотетическим типа Circle):

void drawCircle(cairo_t *cr, int x, int y, int radius, float r, float g, float b, float a) { 
    cairo_set_source_rgba(cr, r, g, b, a); 
    cairo_arc(cr, x, y, radius, 0, 2*M_PI); 
    cairo_stroke_preserve(cr); // keep the arc so that we can call cairo_fill 
    cairo_fill(cr); 
} 

void functionThatDrawsCircles(cairo_surface_t* surface, Circle* circles, int num) { 
    cairo_t* cr = cairo_create(surface); 
    for(int i = 0; i < num; i++) { 
     drawCircle(cr, circles[i].x, circles[i].y, 10, circles[i].r, circles[i].g, circles[i].b, 1.0); 
    } 
    cairo_destroy(cr); 
    gtk_widget_queue_draw_area(GTK_WIDGET(frame2), 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); 
} 
+0

Пробовал это раньше, похоже, что он не имеет никакого эффекта. –

+1

Возможно, вы также должны называть 'cairo_fill' вместо' cairo_fill_preserve', если вам не нужен этот путь дуги после вызова drawCircle. Кроме того, 'gtk_widget_queue_draw_area' потребляет память за вызов до тех пор, пока основной цикл не станет бездействующим, поэтому, если вы, вероятно, не хотите создавать прямоугольники недействительности в drawCircle (перемещайте его снаружи и вызываете только один раз для каждого кадра/обновления и т. Д.) –

+0

Done что, я думаю, что он сохраняет некоторую память, но должна ли программа использовать 500 МБ ОЗУ после 15 повторов? –

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