2016-01-26 5 views
0

Я использую библиотеку Pango рядом с Каиром, без GTK, в приложении для тестового диска, которое я сейчас компилирую на MacOSX. У меня есть проблема утечки памяти, что я проследили к этой функции:Утечка памяти в Pango

void draw_with_cairo (void) 
{ 
    PangoLayout *layout; 
    PangoFontDescription *desc; 
    int i; 

    cairo_save (cr); 
    cairo_scale (cr, 1, -1); 
    cairo_translate (cr, 0, -HEIGHT); 

    cairo_translate (cr, 400, 300); 

    layout = pango_cairo_create_layout (cr); 

    pango_layout_set_text (layout, "Test", -1); 
    desc = pango_font_description_from_string ("‌BMitra 32"); 
    pango_layout_set_font_description (layout, desc); 
    pango_font_description_free (desc); 

    for (i = 0; i < 12; i++) 
    { 
     int width, height; 
     double angle = iter + (360.0 * i)/12; 
     double red; 

     cairo_save (cr); 

     red = (1 + cos ((angle - 60) * G_PI/180.))/2; 
     cairo_set_source_rgb (cr, red, 0, 1.0 - red); 

     cairo_rotate (cr, angle * G_PI/180.); 

     pango_cairo_update_layout (cr, layout); 

     pango_layout_get_size (layout, &width, &height); 
     cairo_move_to (cr, - ((double)width/PANGO_SCALE)/2, - 250); 
     pango_cairo_show_layout (cr, layout); 

     cairo_restore (cr); 
    } 

    cairo_restore (cr); 
    g_object_unref (layout); 

} 

Эта процедура вызывается много, может быть, сто раз в секунду. И утечка памяти огромна, около 30 МБ в 3 сек. И имеет постоянную скорость. Когда я сравниваю этот код, мне кажется, что это очень хорошо. Я искал это, нашел много ссылок на утечки памяти при использовании pango в приложениях Gtk, и все они ищут патч в pango или gtk. Я действительно озадачен и не могу поверить, что в сильно используемой библиотеке, таком как pango, будет такая ошибка, и подумайте, что это проблема с моим собственным кодом. Любые предложения приветствуются.

Это результат VMMap для кода Ули:

Executing vmmap -resident 25897 | grep TOTAL at beginning of main() 
TOTAL       321.3M 126.2M  485 
TOTAL        18.0M  200K  1323  173K  0%  2 
Executing vmmap -resident 25897 | grep TOTAL after cairo init 
TOTAL       331.3M 126.4M  489 
TOTAL        27.0M  224K  1327  1155K  4%  6 
Executing vmmap -resident 25897 | grep TOTAL after one iteration 
TOTAL       383.2M 143.9M  517 
TOTAL        37.2M  3368K  18634  3423K  8%  5 
Executing vmmap -resident 25897 | grep TOTAL after loop 
TOTAL       481.6M 244.1M  514 
TOTAL        137.2M  103.7M  151961  66.4M  48%  6 
Executing vmmap -resident 25897 | grep TOTAL at end 
TOTAL       481.6M 244.1M  520 
TOTAL        136.3M  103.1M  151956  65.4M  48%  11 

И это нефильтрованный выход последней ступени:

Executing vmmap -resident 25751 at end 
Process:   main [25751] 
Path:   /PATH/OMITTED/main 
Load Address: 0x109b9c000 
Identifier:  main 
Version:   ??? 
Code Type:  X86-64 
Parent Process: bash [837] 

Date/Time:  2016-01-30 23:28:35.866 +0330 
Launch Time:  2016-01-30 23:27:35.148 +0330 
OS Version:  Mac OS X 10.11.2 (15C50) 
Report Version: 7 
Analysis Tool: /Applications/Xcode.app/Contents/Developer/usr/bin/vmmap 
Analysis Tool Version: Xcode 7.0.1 (7A1001) 
---- 

Virtual Memory Map of process 25751 (main) 
Output report format: 2.4 -- 64-bit process 
VM page size: 4096 bytes 

==== Non-writable regions for process 25751 

==== Legend 
SM=sharing mode: 
    COW=copy_on_write PRV=private NUL=empty ALI=aliased 
    SHM=shared ZER=zero_filled S/A=shared_alias 

==== Summary for process 25751 
ReadOnly portion of Libraries: Total=219.6M resident=112.2M(51%) swapped_out_or_unallocated=107.5M(49%) 
Writable regions: Total=155.7M written=5448K(3%) resident=104.1M(67%) swapped_out=0K(0%) unallocated=51.6M(33%) 

           VIRTUAL RESIDENT REGION 
REGION TYPE      SIZE  SIZE COUNT (non-coalesced) 
===========      ======= ======== ======= 
Activity Tracing     2048K  12K  2 
Dispatch continuations   8192K  32K  2 
Kernel Alloc Once     8K  8K  3 
MALLOC guard page     32K  0K  7 
MALLOC metadata     364K  84K  11 
MALLOC_LARGE      260K  260K  2   see MALLOC ZONE table below 
MALLOC_LARGE (empty)    980K  668K  2   see MALLOC ZONE table below 
MALLOC_LARGE metadata    4K  4K  2   see MALLOC ZONE table below 
MALLOC_SMALL      32.0M  880K  3   see MALLOC ZONE table below 
MALLOC_TINY      104.0M 102.1M  7   see MALLOC ZONE table below 
STACK GUARD      56.0M  0K  3 
Stack        8264K  60K  3 
VM_ALLOCATE       16K  8K  2 
__DATA       16.7M 13.6M  217 
__IMAGE       528K  104K  2 
__LINKEDIT      92.4M 22.5M  34 
__TEXT       127.2M 89.6M  220 
__UNICODE       552K  476K  2 
mapped file      32.2M 13.7M  4 
shared memory      328K  172K  10 
===========      ======= ======== ======= 
TOTAL       481.6M 244.3M  518 

           VIRTUAL RESIDENT ALLOCATION  BYTES   REGION 
MALLOC ZONE       SIZE  SIZE  COUNT ALLOCATED % FULL COUNT 
===========      ======= ========= ========= ========= ====== ====== 
DefaultMallocZone_0x109bd0000  136.3M  103.2M  151952  65.4M  48%  10 
GFXMallocZone_0x109bd3000    0K   0K   0   0K    0 
===========      ======= ========= ========= ========= ====== ====== 
TOTAL        136.3M  103.2M  151952  65.4M  48%  10 

я опустил часть незаписываемых регионов, потому что это было переполненные пределы стека перекрытия!

+0

У вас есть личный пример, показывающий проблему, с которой я мог бы попробовать? –

+0

Какая версия Pango вы используете? Google нашел https://bugzilla.gnome.org/show_bug.cgi?id=474708, который является утечкой памяти, которая, по-видимому, была зафиксирована в Pango 1.18.2. –

+0

Я только что проверил, pango-1.38.1. На самом деле он был последним в macports. Думаю, это неподтвержденная ошибка. Но после всех этих поисков я потерял доверие к pango! Существует так много сообщений об утечках памяти здесь и там, это не должно иметь место в хорошо структурированном коде. –

ответ

1

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

#include <cairo.h> 
#include <math.h> 
#include <pango/pangocairo.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

#define HEIGHT 500 
#define WIDTH 500 

void draw_with_cairo (cairo_t *cr) 
{ 
    PangoLayout *layout; 
    PangoFontDescription *desc; 
    int i; 

    cairo_save (cr); 
    cairo_scale (cr, 1, -1); 
    cairo_translate (cr, 0, -HEIGHT); 

    cairo_translate (cr, 400, 300); 

    layout = pango_cairo_create_layout (cr); 

    pango_layout_set_text (layout, "Test", -1); 
    desc = pango_font_description_from_string ("‌BMitra 32"); 
    pango_layout_set_font_description (layout, desc); 
    pango_font_description_free (desc); 

    for (i = 0; i < 12; i++) 
    { 
     int width, height; 
     double angle = i + (360.0 * i)/12; 
     double red; 

     cairo_save (cr); 

     red = (1 + cos ((angle - 60) * G_PI/180.))/2; 
     cairo_set_source_rgb (cr, red, 0, 1.0 - red); 

     cairo_rotate (cr, angle * G_PI/180.); 

     pango_cairo_update_layout (cr, layout); 

     pango_layout_get_size (layout, &width, &height); 
     cairo_move_to (cr, - ((double)width/PANGO_SCALE)/2, - 250); 
     pango_cairo_show_layout (cr, layout); 

     cairo_restore (cr); 
    } 

    cairo_restore (cr); 
    g_object_unref (layout); 
} 

static void print_memory_usage(const char *comment) 
{ 
    char buffer[1024]; 
    sprintf(buffer, "grep -E VmPeak\\|VmSize /proc/%d/status", getpid()); 
    printf("Executing %s %s\n", buffer, comment); 
    system(buffer); 
} 

int main() 
{ 
    cairo_surface_t *s; 
    cairo_t *cr; 
    int i; 

    print_memory_usage("at beginning of main()"); 

    s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, WIDTH, HEIGHT); 
    cr = cairo_create(s); 

    print_memory_usage("after cairo init"); 

    draw_with_cairo(cr); 
    print_memory_usage("after one iteration"); 

    for (i = 0; i < 100 * 1000; i++) 
     draw_with_cairo(cr); 

    print_memory_usage("after loop"); 

    cairo_surface_destroy(s); 
    cairo_destroy(cr); 

    print_memory_usage("at end"); 
    return 0; 
} 

Выход для меня (без следов каких-либо утечек памяти):

Executing grep -E VmPeak\|VmSize /proc/31881/status at beginning of main() 
VmPeak: 76660 kB 
VmSize: 76660 kB 
Executing grep -E VmPeak\|VmSize /proc/31881/status after cairo init 
VmPeak: 77640 kB 
VmSize: 77640 kB 
Executing grep -E VmPeak\|VmSize /proc/31881/status after one iteration 
VmPeak: 79520 kB 
VmSize: 79520 kB 
Executing grep -E VmPeak\|VmSize /proc/31881/status after loop 
VmPeak: 79520 kB 
VmSize: 79520 kB 
Executing grep -E VmPeak\|VmSize /proc/31881/status at end 
VmPeak: 79520 kB 
VmSize: 78540 kB 

P.S .: Я испытал это на испытательную Debian amd64 уточненный.

+0

Так что, я думаю, проблема в версии для mac pango. Я вижу утечку, и это определенно в этой рутине. На самом деле у меня на пальце указано, что это макет панго. –

+0

Ну, это сложная ситуация, я вообще не хочу менять панго! –

+0

Что-то вроде выше воспроизводит вашу проблему? (После удаления/proc-magic, я думаю, замена этого с помощью getrusage() имеет смысл) –