Memory Leaks in some functions of MagickWand

The MagickWand interface is a new high-level C API interface to ImageMagick core methods. We discourage the use of the core methods and encourage the use of this API instead. Post MagickWand questions, bug reports, and suggestions to this forum.
Post Reply
javiersm

Memory Leaks in some functions of MagickWand

Post by javiersm »

Hi!

I'm using MagickWand to make an application with some text/image effects and I have a problem when I use Valgrind to check memory leaks.

The message that Valgrind shows me is :

246,734 (8,316 direct, 238,418 indirect) bytes in 15 blocks are definitely lost in loss record 36 of 37
==2266== at 0x47BAA25: malloc (vg_replace_malloc.c:207)
==2266== by 0x49C131D: AcquireMagickMemory (memory.c:335)
==2266== by 0x49C1374: AcquireQuantumMemory (memory.c:409)
==2266== by 0x491B1D6: AcquirePixelCacheNexus (cache.c:285)
==2266== by 0x491B009: AcquirePixelCacheInfo (cache.c:228)
==2266== by 0x49AD1A6: AcquireImage (image.c:182)
==2266== by 0x7593B74: ???
==2266== by 0x493FE0C: ReadImage (constitute.c:516)
==2266== by 0x49159EF: BlobToImage (blob.c:354)
==2266== by 0x487949B: MagickReadImageBlob (magick-image.c:7659)
==2266== by 0x80492C8: ImageCrop (in /data/jhub/_prod/server_wwand/temp/WrapWand/wand)
==2266== by 0x804A746: main (in /data/jhub/_prod/server_wwand/temp/WrapWand/wand)

It seems like is in MagickReadImageBlob() function where is the memory leak, my question is: Is necesary to use some function to free memory like MagickRelinquishMemory() or to do some specific action after or before it to avoid this problem? Thank you very much.

Best regards.
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Memory Leaks in some functions of MagickWand

Post by magick »

We tried reproducing the leak with ImageMagick 6.4.9-2, the current release and valgrind reported no leaks. We used the commands and code below. See if you get a leak with our test case. If not, you will need to provide a test case so we can reproduce the leak.
  • cc `MagickWand-config --cflags --cppflags` -o wand wand.c `MagickWand-config --ldflags --libs`
    convert logo: logo.pnm
    valgrind --leak-check=full wand < logo.pnm
    ...
    definitely lost: 0 bytes in 0 blocks.
The code is:

Code: Select all

#include <stdlib.h>
#include <wand/MagickWand.h>

int main() {
  MagickWand *magick_wand;
  unsigned char blob[921615];

  fread(blob,921615,1,stdin);
  MagickWandGenesis();
  magick_wand=NewMagickWand();
  MagickReadImageBlob(magick_wand,blob,921615);
  MagickWriteImage(magick_wand,"logo.miff");
  DestroyMagickWand(magick_wand);
  MagickWandTerminus();
}
javiersm

Re: Memory Leaks in some functions of MagickWand

Post by javiersm »

Hi!

Thanks for your attention. I've installed over the previous version (6.4.8-3) the current version (6.4.9-2) because i didn't find an official post of how to remove first ImageMagcik, anyway, when I write

Code: Select all

convert -version 
in console the system returns me:

Code: Select all

Version: ImageMagick 6.4.9-2 2009-02-09 Q16 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2009 ImageMagick Studio LLC
And I also be sure that libMagickCore.so and libMagickWand.so points to the new .so that the install created in the machine.

With this version your test program doesn't have memory leaks, and also my program doesn't have in that function, but now appeared in other place. My code is:

Code: Select all

#include <wand/MagickWand.h>                                                                                                                                  

void set_tile_pattern(DrawingWand *d_wand,const char *pattern_name,const char *pattern_file,float rows, float columns)
{                                                                                                                     
        MagickBooleanType bResult;                                                                                    
        MagickWand *t_wand = NewMagickWand();                                                                         

        bResult = MagickReadImage(t_wand,pattern_file);

        printf("TEXTURE FILE : %d\n",bResult);

        MagickResizeImage(t_wand,rows,columns, LanczosFilter,1);

        DrawPushPattern(d_wand, pattern_name+1, 0, 0, rows,columns);
        DrawComposite(d_wand, OverCompositeOp, 0, 0, 0, 0, t_wand); 
        DrawPopPattern(d_wand);                                     
        DrawSetFillPatternURL(d_wand, pattern_name);                
        t_wand = DestroyMagickWand(t_wand);                         
}                                                                   

main()
{     

        MagickWandGenesis();

        MagickWand* wand = NewMagickWand();
        PixelWand* pwand = NewPixelWand(); 
        DrawingWand* dwand = NewDrawingWand();
        PixelSetColor(pwand,"none");          
        float lcolumns = 300;
        float lrows = 300;
        MagickWand* textureWand = NewMagickWand();                                
        MagickNewImage(textureWand,lcolumns,lrows,pwand);                         

        const char* pattern_name = "#none";
        const char* pattern_file = "letras.jpg";

        set_tile_pattern(dwand,pattern_name,pattern_file,lcolumns,lrows);

        PixelSetColor(pwand,"none");

        DrawSetFont(dwand,"Utopia-Regular");
        DrawAnnotation(dwand,0,0,"hello");
        MagickDrawImage(textureWand,dwand);

        PixelSetColor(pwand,"none");
        MagickBorderImage(textureWand,pwand,5,5);

        wand = CloneMagickWand(textureWand);

        textureWand = DestroyMagickWand(textureWand);
        pwand = DestroyPixelWand(pwand);
        dwand = DestroyDrawingWand(dwand);

        wand = DestroyMagickWand(wand);

        MagickWandTerminus();

}
Compiled with:



And valgrind returns to me:

Code: Select all

==31326== 1,276 (24 direct, 1,252 indirect) bytes in 2 blocks are definitely lost in loss record 21 of 37                                                     
==31326==    at 0x47BAA25: malloc (vg_replace_malloc.c:207)                                                                                                   
==31326==    by 0xBB7052: FcConfigAddEdit (in /usr/lib/libfontconfig.so.1.0.4)                                                                                
==31326==    by 0xBAA7DF: (within /usr/lib/libfontconfig.so.1.0.4)                                                                                            
==31326==    by 0xBAA95C: (within /usr/lib/libfontconfig.so.1.0.4)                                                                                            
==31326==    by 0xB8324E: (within /usr/lib/libexpat.so.0.5.0)                                                                                                 
==31326==    by 0xB827D8: (within /usr/lib/libexpat.so.0.5.0)                                                                                                 
==31326==    by 0xB85455: (within /usr/lib/libexpat.so.0.5.0)                                                                                                 
==31326==    by 0xB85260: (within /usr/lib/libexpat.so.0.5.0)                                                                                                 
==31326==    by 0xB821C9: XML_ParseBuffer (in /usr/lib/libexpat.so.0.5.0)                                                                                     
==31326==    by 0xBAAD59: FcConfigParseAndLoad (in /usr/lib/libfontconfig.so.1.0.4)                                                                           
==31326==    by 0xBB1A9A: FcInitLoadConfig (in /usr/lib/libfontconfig.so.1.0.4)                                                                               
==31326==    by 0xBB1AEB: FcInitLoadConfigAndFonts (in /usr/lib/libfontconfig.so.1.0.4)                                                                       
==31326==                                                                                                                                                     
==31326==                                                                                                                                                     
==31326== 268 (12 direct, 256 indirect) bytes in 1 blocks are definitely lost in loss record 22 of 37                                                         
==31326==    at 0x47BAA25: malloc (vg_replace_malloc.c:207)                                                                                                   
==31326==    by 0xBBB052: FcBlanksCreate (in /usr/lib/libfontconfig.so.1.0.4)                                                                                 
==31326==    by 0xBA92C6: (within /usr/lib/libfontconfig.so.1.0.4)                                                                                            
==31326==    by 0xBAA976: (within /usr/lib/libfontconfig.so.1.0.4)                                                                                            
==31326==    by 0xB8324E: (within /usr/lib/libexpat.so.0.5.0)                                                                                                 
==31326==    by 0xB827D8: (within /usr/lib/libexpat.so.0.5.0)                                                                                                 
==31326==    by 0xB821C9: XML_ParseBuffer (in /usr/lib/libexpat.so.0.5.0)                                                                                     
==31326==    by 0xBAAD59: FcConfigParseAndLoad (in /usr/lib/libfontconfig.so.1.0.4)                                                                           
==31326==    by 0xBB1A9A: FcInitLoadConfig (in /usr/lib/libfontconfig.so.1.0.4)                                                                               
==31326==    by 0xBB1AEB: FcInitLoadConfigAndFonts (in /usr/lib/libfontconfig.so.1.0.4)                                                                       
==31326==    by 0x4A275E0: LoadFontConfigFonts (type.c:692)                                                                                                   
==31326==    by 0x4A27C04: InitializeTypeList (type.c:811)                                                                                                    
==31326==                                                                                                                                                     
==31326==                                                                                                                                                     
==31326== 21,036 (4,144 direct, 16,892 indirect) bytes in 4 blocks are definitely lost in loss record 35 of 37                                                
==31326==    at 0x47BAA25: malloc (vg_replace_malloc.c:207)                                                                                                   
==31326==    by 0x49C542D: AcquireMagickMemory (memory.c:335)                                                                                                 
==31326==    by 0x4886484: NewMagickWand (magick-wand.c:1039)                                                                                                 
==31326==    by 0x8048BE1: main (in /data/jhub/_prod/server_wwand/temp/WrapWand/split/texture)                                                                
==31326==                                                                                                                                                     
==31326== LEAK SUMMARY:
==31326==    definitely lost: 4,180 bytes in 7 blocks.
==31326==    indirectly lost: 18,400 bytes in 86 blocks.
==31326==      possibly lost: 0 bytes in 0 blocks.
==31326==    still reachable: 22,893 bytes in 693 blocks.
==31326==         suppressed: 0 bytes in 0 blocks.
So know seems to be the problem in NewMagickWand() function, any help will be appreciated, thanks.

Best regards.
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Memory Leaks in some functions of MagickWand

Post by magick »

The leak is in your code, not MagickWand-- you have
  • MagickWand* wand = NewMagickWand();
however you fail to destroy it before you reassign it from a cloned textureWand:
  • wand = CloneMagickWand(textureWand);
You also use NewMagickImage() but do not assign it to any variable and do not destroy the resources that it consumes:
  • MagickNewImage(textureWand,lcolumns,lrows,pwand);
javiersm

Re: Memory Leaks in some functions of MagickWand

Post by javiersm »

Ok, sorry about my own errors I don't have seen too many documentation about avoiding memory leaks using MagickWand and tried myself.

But what about this simple code? Where is the error? Where I can find documentation to don't bother you with every leak that appears in my code? Thanks.

Code: Select all

#include <wand/MagickWand.h>

main()
{
        MagickWandGenesis();

        MagickBooleanType bResult;
        MagickWand *t_wand = NewMagickWand();
        bResult = MagickReadImage(t_wand,"letras.jpg");
        bResult = MagickResizeImage(t_wand,300,300, LanczosFilter,1);
        t_wand = DestroyMagickWand(t_wand);

        MagickWandTerminus();
}

Code: Select all

==1219== 16 bytes in 1 blocks are still reachable in loss record 1 of 3                                                                                      
==1219==    at 0x47BBF99: calloc (vg_replace_malloc.c:397)                                                                                                   
==1219==    by 0x56F308: _dlerror_run (in /lib/libdl-2.3.3.so)                                                                                               
==1219==    by 0x56EDA3: dlopen@@GLIBC_2.1 (in /lib/libdl-2.3.3.so)                                                                                          
==1219==    by 0x4A58EF6: vm_open (dlopen.c:194)                                                                                                             
==1219==    by 0x4A55AD1: tryall_dlopen (ltdl.c:434)                                                                                                         
==1219==    by 0x4A55D79: find_module (ltdl.c:532)                                                                                                           
==1219==    by 0x4A56D9A: try_dlopen (ltdl.c:1390)                                                                                                           
==1219==    by 0x4A57634: lt_dlopenadvise (ltdl.c:1632)                                                                                                      
==1219==    by 0x4A5757C: lt_dlopen (ltdl.c:1590)                                                                                                            
==1219==    by 0x49C7DC9: OpenModule (module.c:1134)                                                                                                         
==1219==    by 0x49C3B0C: GetMagickInfo (magick.c:459)                                                                                                       
==1219==    by 0x49B76D0: SetImageInfo (image.c:3655)                                                                                                        
==1219==                                                                                                                                                     
==1219==                                                                                                                                                     
==1219== 96 (8 direct, 88 indirect) bytes in 2 blocks are definitely lost in loss record 2 of 3                                                              
==1219==    at 0x47BAA25: malloc (vg_replace_malloc.c:207)                                                                                                   
==1219==    by 0x49C542D: AcquireMagickMemory (memory.c:335)                                                                                                 
==1219==    by 0x49C5484: AcquireQuantumMemory (memory.c:409)                                                                                                
==1219==    by 0x491D536: AcquirePixelCacheNexus (cache.c:285)                                                                                               
==1219==    by 0x491D369: AcquirePixelCacheInfo (cache.c:228)                                                                                                
==1219==    by 0x49B04BA: AcquireImage (image.c:179)                                                                                                         
==1219==    by 0x7586789: ???                                                                                                                                
==1219==    by 0x49422D0: ReadImage (constitute.c:516)                                                                                                       
==1219==    by 0x487B388: MagickReadImage (magick-image.c:7736)                                                                                              
==1219==    by 0x80486E8: main (in /data/jhub/_prod/server_wwand/temp/WrapWand/split/Texture/prueba)                                                         
==1219==                                                                                                                                                     
==1219==                                                                                                                                                     
==1219== 88 bytes in 2 blocks are indirectly lost in loss record 3 of 3                                                                                      
==1219==    at 0x47BAA25: malloc (vg_replace_malloc.c:207)                                                                                                   
==1219==    by 0x49C542D: AcquireMagickMemory (memory.c:335)                                                                                                 
==1219==    by 0x491D561: AcquirePixelCacheNexus (cache.c:291)                                                                                               
==1219==    by 0x491D369: AcquirePixelCacheInfo (cache.c:228)                                                                                                
==1219==    by 0x49B04BA: AcquireImage (image.c:179)                                                                                                         
==1219==    by 0x7586789: ???                                                                                                                                
==1219==    by 0x49422D0: ReadImage (constitute.c:516)                                                                                                       
==1219==    by 0x487B388: MagickReadImage (magick-image.c:7736)                                                                                              
==1219==    by 0x80486E8: main (in /data/jhub/_prod/server_wwand/temp/WrapWand/split/Texture/prueba)                                                         
==1219==                                                                                                                                                     
==1219== LEAK SUMMARY:                                                                                                                                       
==1219==    definitely lost: 8 bytes in 2 blocks.                                                                                                            
==1219==    indirectly lost: 88 bytes in 2 blocks.                                                                                                           
==1219==      possibly lost: 0 bytes in 0 blocks.                                                                                                            
==1219==    still reachable: 16 bytes in 1 blocks.
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Memory Leaks in some functions of MagickWand

Post by magick »

There was a 16-byte leak when cloning an image. The leak is fixed in the ImageMagick-6.4.9-3 release. Thanks for alerting us to the problem.
javiersm

Re: Memory Leaks in some functions of MagickWand

Post by javiersm »

Thanks! that memory leak is solved with the current version. There is another leak that has my code, this time related with the fonts I think.

My C code is:

Code: Select all

#include <wand/MagickWand.h>                   

main()
{     
        MagickWandGenesis();

        unsigned char *psFileStreamOutput = NULL;
        MagickWand* wand = NewMagickWand();      
        MagickWand* wand_background = NewMagickWand();
        DrawingWand* dwand = NewDrawingWand();        
        PixelWand* pwand = NewPixelWand();            
        MagickBooleanType bResult;                    
        char szColor[50];                              

        float columns = 600;
        float rows = 400;   

        ClearMagickWand(wand);

        DrawSetGravity(dwand,CenterGravity);
        DrawSetFontSize(dwand,50);
        bResult = DrawSetFont(dwand,"Utopia-Regular");

        strcpy(szColor,"rgba(255,0,0,0.5)");

        bResult = PixelSetColor(pwand,szColor);
        DrawSetFillColor(dwand,pwand);
        DrawAnnotation(dwand,0,0,"hello");

        bResult = MagickNewImage(wand,columns,rows,pwand);
        bResult = MagickDrawImage(wand,dwand);
        bResult = MagickSetImageFormat(wand,"png");

        bResult = PixelSetColor(pwand,"none");
        ClearMagickWand(wand_background);
        bResult = MagickNewImage(wand_background,1200,1000, pwand);
        bResult = MagickSetImageFormat(wand_background, "png");
        bResult = MagickTrimImage(wand,0);

        bResult = MagickCompositeImage(wand_background,wand, OverCompositeOp,0,0);
        int *iSizeOutput = malloc(1*sizeof(int));
        psFileStreamOutput = MagickGetImageBlob(wand_background, (size_t *)iSizeOutput );

        bResult = MagickWriteImage(wand_background,"noEffect.png");

        wand =  DestroyMagickWand( wand );
        wand_background = DestroyMagickWand( wand_background );
        pwand = DestroyPixelWand( pwand );
        dwand = DestroyDrawingWand(dwand);

        psFileStreamOutput = MagickRelinquishMemory(psFileStreamOutput);
        free(iSizeOutput);

        MagickWandTerminus();

}
And valgrind shows me :

Code: Select all

==23948== 1,276 (24 direct, 1,252 indirect) bytes in 2 blocks are definitely lost in loss record 8 of 45                                                      
==23948==    at 0x47BAA25: malloc (vg_replace_malloc.c:207)                                                                                                   
==23948==    by 0xBB7052: FcConfigAddEdit (in /usr/lib/libfontconfig.so.1.0.4)                                                                                
==23948==    by 0xBAA7DF: (within /usr/lib/libfontconfig.so.1.0.4)                                                                                            
==23948==    by 0xBAA95C: (within /usr/lib/libfontconfig.so.1.0.4)                                                                                            
==23948==    by 0xB8324E: (within /usr/lib/libexpat.so.0.5.0)                                                                                                 
==23948==    by 0xB827D8: (within /usr/lib/libexpat.so.0.5.0)                                                                                                 
==23948==    by 0xB85455: (within /usr/lib/libexpat.so.0.5.0)                                                                                                 
==23948==    by 0xB85260: (within /usr/lib/libexpat.so.0.5.0)                                                                                                 
==23948==    by 0xB821C9: XML_ParseBuffer (in /usr/lib/libexpat.so.0.5.0)                                                                                     
==23948==    by 0xBAAD59: FcConfigParseAndLoad (in /usr/lib/libfontconfig.so.1.0.4)                                                                           
==23948==    by 0xBB1A9A: FcInitLoadConfig (in /usr/lib/libfontconfig.so.1.0.4)                                                                               
==23948==    by 0xBB1AEB: FcInitLoadConfigAndFonts (in /usr/lib/libfontconfig.so.1.0.4)                                                                       
==23948==                                                                                                                                                     
==23948==                                                                                                                                                     
==23948== 268 (12 direct, 256 indirect) bytes in 1 blocks are definitely lost in loss record 9 of 45                                                          
==23948==    at 0x47BAA25: malloc (vg_replace_malloc.c:207)                                                                                                   
==23948==    by 0xBBB052: FcBlanksCreate (in /usr/lib/libfontconfig.so.1.0.4)                                                                                 
==23948==    by 0xBA92C6: (within /usr/lib/libfontconfig.so.1.0.4)                                                                                            
==23948==    by 0xBAA976: (within /usr/lib/libfontconfig.so.1.0.4)                                                                                            
==23948==    by 0xB8324E: (within /usr/lib/libexpat.so.0.5.0)                                                                                                 
==23948==    by 0xB827D8: (within /usr/lib/libexpat.so.0.5.0)                                                                                                 
==23948==    by 0xB821C9: XML_ParseBuffer (in /usr/lib/libexpat.so.0.5.0)                                                                                     
==23948==    by 0xBAAD59: FcConfigParseAndLoad (in /usr/lib/libfontconfig.so.1.0.4)                                                                           
==23948==    by 0xBB1A9A: FcInitLoadConfig (in /usr/lib/libfontconfig.so.1.0.4)                                                                               
==23948==    by 0xBB1AEB: FcInitLoadConfigAndFonts (in /usr/lib/libfontconfig.so.1.0.4)                                                                       
==23948==    by 0x4A27664: LoadFontConfigFonts (type.c:692)                                                                                                   
==23948==    by 0x4A27C88: InitializeTypeList (type.c:811)

==23948== LEAK SUMMARY:                                                                                                                                       
==23948==    definitely lost: 36 bytes in 3 blocks.                                                                                                           
==23948==    indirectly lost: 1,508 bytes in 78 blocks.                                                                                                       
==23948==      possibly lost: 0 bytes in 0 blocks.                                                                                                            
==23948==    still reachable: 275,896 bytes in 4,452 blocks.                                                                                                  
==23948==         suppressed: 0 bytes in 0 blocks.
I don't know why this happens because executing the command:

Code: Select all

convert -list font
I can see in the output:

Code: Select all

  Font: Utopia-Regular
    family: Utopia
    style: Normal
    stretch: UltraExpanded
    weight: 400
    glyphs: /usr/X11R6/lib/X11/fonts/Type1/UTRG____.pfa
Any help will be apreciated, thanks! Best Regards.
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Memory Leaks in some functions of MagickWand

Post by magick »

The leak is in the fontconfig delegate library and appears to be fixed in recent versions of the library. We're using fontconfig-2.6.95-1 and your program returns:
  • ==4084== LEAK SUMMARY:
    ==4084== definitely lost: 0 bytes in 0 blocks.
Post Reply