我正在使用Pango库和Cairo,没有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);
}
这个例程被调用了很多次,也许在一秒钟内被调用一百次。而且内存泄漏很大,3秒内约为30MB,并且速率恒定。当我比较这段代码时,对我来说似乎很好。我已经搜索了这个,在 Gtk 应用程序中使用 pango 时发现了许多对内存泄漏的引用,他们都在 pango 或 gtk 中寻找补丁。我真的很困惑,不敢相信像pango这样频繁使用的库中会有这样的错误,并认为这是我自己的代码的问题。任何建议不胜感激。
这是 Uli 代码的 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
我省略了不可写区域部分,因为它溢出了堆栈溢出限制!
我没有看到任何内存泄漏。以下程序在运行上述函数 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 %sn", 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
PS:我在最新的 debian 测试 amd64 上对此进行了测试。