Bug 67171

Summary: Memory Leak in win32-display-surface
Product: cairo Reporter: googy303 <ilja.maier>
Component: win32 backendAssignee: cairo-bugs mailing list <cairo-bugs>
Status: RESOLVED MOVED QA Contact: cairo-bugs mailing list <cairo-bugs>
Severity: major    
Priority: medium CC: fredbca21
Version: 1.12.16   
Hardware: x86 (IA32)   
OS: Windows (All)   
Whiteboard:
i915 platform: i915 features:
Bug Depends on:    
Bug Blocks: 84197    
Attachments: Proposed patch to fix the leak

Description googy303 2013-07-22 12:43:40 UTC
cairo_surface_t *
cairo_win32_surface_create (HDC hdc)
{ ...
device = _cairo_win32_device_get ();
--> call device malloc
...
}

static void
_cairo_win32_device_destroy (void *device)
{
    free (device);
}
in cairo-win32-device.c will never called, due to ref counter.


Output window in VC2010:

Dumping objects ->
win32/cairo-win32-device.c(154) : {197} normal block at 0x00857F40, 72 bytes long.
 Data: <                > 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
Object dump complete.
Detected memory leaks!

72 bytes is the size of device structure.

With best regards
Comment 1 Chris Wilson 2013-07-22 12:51:01 UTC
Yes. The cairo_win32_device is a singleton that is meant to be cleaned up by cairo_debug_reset_static_data -- only it is not coupled into that yet.
Comment 2 googy303 2013-07-22 13:18:44 UTC
Hello Chris,

can you give me a hint where to release it, so I have a preliminary fix? When will the fix be available in the git repo?

Thanks.
Comment 3 Fred 2016-04-06 07:59:55 UTC
Created attachment 122751 [details] [review]
Proposed patch to fix the leak

Here is a simple patch to fix the issue by adding the appropriate call in the debug reset static data function.
Comment 4 Martin B 2016-05-05 00:48:16 UTC
(In reply to Fred from comment #3)
> Created attachment 122751 [details] [review] [review]
> Proposed patch to fix the leak
> 
> Here is a simple patch to fix the issue by adding the appropriate call in
> the debug reset static data function.

Hi,

I tried the solution your proposed but I'm still getting leak on :

_cairo_win32_device_get
---> device = malloc (sizeof (*device));

Dumping objects ->
{537} normal block at 0x01141E10, 1032 bytes long.
 Data: <        8+   *  > 10 1E 14 01 C8 19 14 01 38 2B CC 01 90 2A CC 01 
{536} normal block at 0x011419C8, 1032 bytes long.
 Data: <        xW   o  > 10 1E 14 01 80 15 14 01 78 57 CC 01 D8 6F CC 01 
{535} normal block at 0x01141580, 1032 bytes long.
 Data: <    8   8v   u  > 10 1E 14 01 38 11 14 01 38 76 CC 01 D8 75 CC 01 
{534} normal block at 0x01141138, 1032 bytes long.
 Data: <      R 8,   ?  > 10 1E 14 01 B8 D7 52 00 38 2C CC 01 A0 3F CC 01 
{394} normal block at 0x0052D7B8, 1032 bytes long.
 Data: <         J   J  > 10 1E 14 01 00 00 00 00 B8 4A CC 01 08 4A CC 01 
{379} normal block at 0x0052B7A8, 52 bytes long.
 Data: <                > 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
Object dump complete.

I use Intel Parallel Inspector too and the same leak is related. Here is the log

P8: Warning: Memory not deallocated: New
 P8.26: Warning: Memory not deallocated: 52 Bytes: New
  h:\developmenttests\cairo\cairo\cairo_1_12_16\src\win32\cairo-win32-device.c(137): Warning X40: Allocation site: Function cairo_win32_device_get: Module H:\DevelopmentTests\Cairo\cairo\Release\MFCTest.exe
  Code snippet:
   135      return cairo_device_reference (__cairo_win32_device);
   136  
  >137      device = malloc (sizeof (*device));
   138  
   139      _cairo_device_init (&device->base, &_cairo_win32_device_backend);

  Stack (1 of 1 instance(s))
  >MFCTest.exe!cairo_win32_device_get - h:\developmenttests\cairo\cairo\cairo_1_12_16\src\win32\cairo-win32-device.c:137
   MFCTest.exe!cairo_win32_surface_create - h:\developmenttests\cairo\cairo\cairo_1_12_16\src\win32\cairo-win32-display-surface.c:983
   MFCTest.exe!WindowProc - h:\developmenttests\cairo\cairo\mfctest\mfctestdlg.cpp:73
   MFCTest.exe!AfxCallWndProc - f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp:240
   MFCTest.exe!AfxWndProc - f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp:402
   USER32.dll!gapfnScSendMessage - C:\Windows\syswow64\USER32.dll:0x162f7
   USER32.dll!GetDC - C:\Windows\syswow64\USER32.dll:0x17311
   USER32.dll!GetThreadDesktop - C:\Windows\syswow64\USER32.dll:0x16de3
   USER32.dll!GetThreadDesktop - C:\Windows\syswow64\USER32.dll:0x16e41
   ntdll.dll!KiUserCallbackDispatcher - C:\Windows\SysWOW64\ntdll.dll:0x10107
   Unknown![Unknown] - :0x0
   USER32.dll!SendMessageW - C:\Windows\syswow64\USER32.dll:0x19773
   USER32.dll!UpdateWindow - C:\Windows\syswow64\USER32.dll:0x23598
   USER32.dll!IsCharAlphaA - C:\Windows\syswow64\USER32.dll:0x3b98d
   USER32.dll!CreateDialogIndirectParamAorW - C:\Windows\syswow64\USER32.dll:0x410ce
   USER32.dll!CreateDialogIndirectParamW - C:\Windows\syswow64\USER32.dll:0x2c654
   MFCTest.exe!CreateDlgIndirect - f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\dlgcore.cpp:312

 P8.30: Warning: Memory not deallocated: 4128 Bytes: New
  h:\test\cairo\cairo\pixman\pixman\pixman-implementation.c(38): Warning X44: Allocation site: Function pixman_implementation_create: Module H:\test\Cairo\cairo\Debug\MFCTest.exe
  Code snippet:
   36      assert (fast_paths);
   37  
  >38      if ((imp = malloc (sizeof (pixman_implementation_t))))
   39      {
   40  	pixman_implementation_t *d;

  Stack (1 of 1 instance(s))
  >MFCTest.exe!pixman_implementation_create - h:\test\cairo\cairo\pixman\pixman\pixman-implementation.c:38
   MFCTest.exe!pixman_implementation_create_mmx - h:\test\cairo\cairo\pixman\pixman\pixman-mmx.c:4021
   MFCTest.exe!pixman_x86_get_implementations - h:\test\cairo\cairo\pixman\pixman\pixman-x86.c:234
   MFCTest.exe!pixman_choose_implementation - h:\test\cairo\cairo\pixman\pixman\pixman-implementation.c:393
   MFCTest.exe!fill_xrgb32_lerp_opaque_spans - h:\test\cairo\cairo\\src\cairo-image-compositor.c:2190
   MFCTest.exe!blit_a8 - h:\test\cairo\cairo\\src\cairo-tor-scan-converter.c:1600
   MFCTest.exe!glitter_scan_converter_render - h:\test\cairo\cairo\\src\cairo-tor-scan-converter.c:1750
   MFCTest.exe!cairo_tor_scan_converter_generate - h:\test\cairo\cairo\\src\cairo-tor-scan-converter.c:1815
   MFCTest.exe!composite_polygon - h:\test\cairo\cairo\\src\cairo-spans-compositor.c:778
   MFCTest.exe!clip_and_composite_polygon - h:\test\cairo\cairo\cairo\src\cairo-spans-compositor.c:945
   MFCTest.exe!cairo_spans_compositor_stroke - h:\test\cairo\cairo\cairo\src\cairo-spans-compositor.c:1059
   MFCTest.exe!cairo_compositor_stroke - h:\test\cairo\cairo\cairo\src\cairo-compositor.c:159
   MFCTest.exe!cairo_image_surface_stroke - h:\test\cairo\cairo\cairo\src\cairo-image-surface.c:958
   MFCTest.exe!cairo_surface_stroke - h:\test\cairo\cairo\cairo\src\cairo-surface.c:2183
   MFCTest.exe!cairo_surface_offset_stroke - h:\test\cairo\cairo\cairo\src\cairo-surface-offset.c:187
   MFCTest.exe!cairo_fallback_compositor_stroke - h:\test\cairo\cairo\cairo\src\cairo-fallback-compositor.c:119
   MFCTest.exe!cairo_compositor_stroke - h:\test\cairo\cairo\cairo\src\cairo-compositor.c:159

 P8.31: Warning: Memory not deallocated: 1032 Bytes: New
  h:\test\cairo\cairo\pixman\pixman\pixman-general.c(239): Warning X45: Allocation site: Function pixman_implementation_create_general: Module H:\test\Cairo\cairo\Debug\MFCTest.exe
  Code snippet:
   237  _pixman_implementation_create_general (void)
   238  {
  >239      pixman_implementation_t *imp = _pixman_implementation_create (NULL, general_fast_path);
   240  
   241      _pixman_setup_combiner_functions_32 (imp);

  Stack (1 of 1 instance(s))
  >MFCTest.exe!pixman_implementation_create_general - h:\test\cairo\cairo\pixman\pixman\pixman-general.c:239
   MFCTest.exe!pixman_choose_implementation - h:\test\cairo\cairo\pixman\pixman\pixman-implementation.c:388
   MFCTest.exe!fill_xrgb32_lerp_opaque_spans - h:\test\cairo\cairo\cairo\src\cairo-image-compositor.c:2190
   MFCTest.exe!blit_a8 - h:\test\cairo\cairo\cairo\src\cairo-tor-scan-converter.c:1600
   MFCTest.exe!glitter_scan_converter_render - h:\test\cairo\cairo\cairo\src\cairo-tor-scan-converter.c:1750
   MFCTest.exe!cairo_tor_scan_converter_generate - h:\test\cairo\cairo\cairo\src\cairo-tor-scan-converter.c:1815
   MFCTest.exe!composite_polygon - h:\test\cairo\cairo\cairo\src\cairo-spans-compositor.c:778
   MFCTest.exe!clip_and_composite_polygon - h:\test\cairo\cairo\cairo\src\cairo-spans-compositor.c:945
   MFCTest.exe!cairo_spans_compositor_stroke - h:\test\cairo\cairo\cairo\src\cairo-spans-compositor.c:1059
   MFCTest.exe!cairo_compositor_stroke - h:\test\cairo\cairo\cairo\src\cairo-compositor.c:159
   MFCTest.exe!cairo_image_surface_stroke - h:\test\cairo\cairo\cairo\src\cairo-image-surface.c:958
   MFCTest.exe!cairo_surface_stroke - h:\test\cairo\cairo\cairo\src\cairo-surface.c:2183
   MFCTest.exe!cairo_surface_offset_stroke - h:\test\cairo\cairo\cairo\src\cairo-surface-offset.c:187
   MFCTest.exe!cairo_fallback_compositor_stroke - h:\test\cairo\cairo\cairo\src\cairo-fallback-compositor.c:119
   MFCTest.exe!cairo_compositor_stroke - h:\test\cairo\cairo\cairo\src\cairo-compositor.c:159
   MFCTest.exe!cairo_win32_display_surface_stroke - h:\test\cairo\cairo\cairo\src\win32\cairo-win32-display-surface.c:844
   MFCTest.exe!cairo_surface_stroke - h:\test\cairo\cairo\cairo\src\cairo-surface.c:2183
Comment 5 Martin B 2016-05-06 01:16:31 UTC
Hold one, the patch is working but I have to call implicitly the function :

		case WM_CLOSE:
		{
			cairo_debug_reset_static_data();
		}
		break;

Now the leak is gone. 

But do I need to call this in release mode too ?
Comment 6 Uli Schlachter 2016-05-08 11:50:13 UTC
All that the patch does is to do more cleanup in cairo_debug_reset_static_data(). So yes, if you want the patch to make a difference, then you have to call this function.

However, this "leak" is really harmless. It's a "one time"-thing and nothing that keeps growing. The only reason why people are interesting in this is to keep their leak detection tool quiet.
Comment 7 Fred 2017-04-13 09:18:51 UTC
It is actually NOT a one-time thing if you call dynamically loaded libraries that are statically linked with cairo. 

Getting rid of leaks (even static) is usually not a bad thing anyway: such static leaks could actually impact external resources (files, system objects) that have to be properly released/cleaned up. (It is fortunately not the case here)
Comment 8 GitLab Migration User 2018-08-25 13:27:50 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/cairo/cairo/issues/19.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.