3d0c/gmf

memory leak

Opened this issue · 1 comments

When running test video-to-image.go with valgrind, got the following results:

==198162== HEAP SUMMARY:
==198162==     in use at exit: 239,337 bytes in 1,148 blocks
==198162==   total heap usage: 3,978 allocs, 2,830 frees, 18,270,904 bytes allocated
==198162== 
==198162== 128 (24 direct, 104 indirect) bytes in 1 blocks are definitely lost in loss record 296 of 349
==198162==    at 0x4848DD0: memalign (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==198162==    by 0x4848F32: posix_memalign (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==198162==    by 0x64D5474: av_malloc (in /usr/lib/x86_64-linux-gnu/libavutil.so.56.70.100)
==198162==    by 0x64D5851: av_mallocz (in /usr/lib/x86_64-linux-gnu/libavutil.so.56.70.100)
==198162==    by 0x64B2347: av_buffer_create (in /usr/lib/x86_64-linux-gnu/libavutil.so.56.70.100)
==198162==    by 0x64B28EB: av_buffer_realloc (in /usr/lib/x86_64-linux-gnu/libavutil.so.56.70.100)
==198162==    by 0x525946D: av_new_packet (in /usr/lib/x86_64-linux-gnu/libavcodec.so.58.134.100)
==198162==    by 0x4AB06D: _cgo_6590a2dc699d_Cfunc_av_new_packet (k:55)
==198162==    by 0x4637EF: runtime.asmcgocall.abi0 (asm_amd64.s:765)
==198162==    by 0x59F0DF: ???
==198162== 
==198162== 3,200 (600 direct, 2,600 indirect) bytes in 25 blocks are definitely lost in loss record 344 of 349
==198162==    at 0x4848DD0: memalign (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==198162==    by 0x4848F32: posix_memalign (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==198162==    by 0x64D5474: av_malloc (in /usr/lib/x86_64-linux-gnu/libavutil.so.56.70.100)
==198162==    by 0x64D5851: av_mallocz (in /usr/lib/x86_64-linux-gnu/libavutil.so.56.70.100)
==198162==    by 0x64B2347: av_buffer_create (in /usr/lib/x86_64-linux-gnu/libavutil.so.56.70.100)
==198162==    by 0x64B28EB: av_buffer_realloc (in /usr/lib/x86_64-linux-gnu/libavutil.so.56.70.100)
==198162==    by 0x525946D: av_new_packet (in /usr/lib/x86_64-linux-gnu/libavcodec.so.58.134.100)
==198162==    by 0x4AB06D: _cgo_6590a2dc699d_Cfunc_av_new_packet (k:55)
==198162==    by 0x4637EF: runtime.asmcgocall.abi0 (asm_amd64.s:765)
==198162==    by 0x42C476: runtime.unlockWithRank (lockrank_off.go:32)
==198162==    by 0x42C476: runtime.unlock (lock_futex.go:112)
==198162==    by 0x42C476: runtime.removefinalizer (mheap.go:1846)
==198162==    by 0x327: ???
==198162==    by 0xC00000019F: ???
==198162== 
==198162== LEAK SUMMARY:
==198162==    definitely lost: 624 bytes in 26 blocks
==198162==    indirectly lost: 2,704 bytes in 52 blocks
==198162==      possibly lost: 3,280 bytes in 7 blocks
==198162==    still reachable: 230,713 bytes in 1,042 blocks
==198162==         suppressed: 0 bytes in 0 blocks

The library is built with the latest release (4.4.2) of FFmpeg:

libavutil      56. 70.100
libavcodec     58.134.100
libavformat    58. 76.100
libavdevice    58. 13.100
libavfilter     7.110.100
libswscale      5.  9.100
libswresample   3.  9.100
libpostproc    55.  9.100

It seems that the memory leak comes from this commit.

The av_new_packet function allocates a buffer for the packet:

int av_new_packet(AVPacket *pkt, int size)                                      
{                                                                               
    AVBufferRef *buf = NULL;                                                    
    int ret = packet_alloc(&buf, size);                                         
    if (ret < 0)                                                                
        return ret;                                                             
                                                                                
    av_init_packet(pkt);                                                        
    pkt->buf      = buf;                                                        
    pkt->data     = buf->data;                                                  
    pkt->size     = size;                                                       
                                                                                
    return 0;                                                                   
}

The buffer is later used in av_read_frame, avcodec_send_packet, etc., where extra references may be added to the buffer, resulting in the memory leak.

I'm not sure if this problem can be trivially fixed without changing gmf's API, or if it's a bug of FFmpeg. Using the deprecated av_init_packet instead of av_new_packet works fine, for now.