Memory leaks Pango中的内存泄漏

Memory leaks Pango中的内存泄漏,memory-leaks,cairo,pango,pangocairo,Memory Leaks,Cairo,Pango,Pangocairo,我在Cairo旁边使用Pango库,没有GTK,我正在MacOSX上编译一个试驾应用程序。我有一个内存泄漏问题,我跟踪到这个函数: 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旁边使用Pango库,没有GTK,我正在MacOSX上编译一个试驾应用程序。我有一个内存泄漏问题,我跟踪到这个函数:

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);

}
这是最后一级的未过滤输出:

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

我省略了不可写区域部分,因为它溢出了堆栈溢出限制

我没有看到任何内存泄漏。以下程序在运行上述函数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;
}

备注:我在最新的debian测试amd64上测试了这个问题。

您有没有任何独立的示例可以说明我可以尝试的问题?您使用的是哪种Pango版本?谷歌发现了一个内存泄漏,这显然是在Pango 1.18.2中修复的。我刚刚检查过,Pango-1.38.1。事实上,这是macports的最新版本。我想这是一个未报告的错误。但是经过这么多的搜索,我已经失去了对pango的信任!到处都有很多关于内存泄漏的报告,这在一个结构良好的代码中是不应该的。顺便说一句,我发现内存泄漏发生在pango_cairo_update_布局函数中。所以我猜问题出在pango的mac版本中。我看到了漏洞,这肯定是在例行程序。事实上,我已经指出这是盘古布局。好吧,这是一个艰难的情况,我不打算修改盘古在所有!像上面这样的事情会重现你的问题吗?(在删除/proc魔法后,我想用getrusage()替换它是有意义的)首先,谢谢你教我!我运行了你的代码,并进行了镜像修改。我没有使用/proc magic(如您所说!),而是按如下方式使用vmmap:“vmmap-resident%d | grep TOTAL”。我只是把它涂成灰色,给我总的内存使用量。我将结果附加到问题文本中。再次感谢。
#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