3d0c / gmf

Go Media Framework
MIT License
885 stars 170 forks source link

memory leak #151

Open ghost opened 2 years ago

ghost commented 2 years ago

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
ghost commented 2 years ago

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.