首页 > 代码库 > ffmpeg : av_free段错误

ffmpeg : av_free段错误

https://ffmpeg.org/pipermail/libav-user/2012-December/003257.html

I get a double free or corruption problem, should really do a bug
report but don‘t have time to decipher the FFmpeg bug reporting page.
I‘ll post it here in case anyone is interested, feel free to ignore.

When using custom IO for reading involves  something like the
following when creating a context:

buffer = (uint8_t*)av_malloc( BUFFER_SIZE );
ctxt = avio_alloc_context( buffer, BUFFER_SIZE, 0, this,
read_function, NULL, NULL );

and then to free it:

av_free( ctxt );
av_free( buffer );

However, if BUFFER_SIZE > 32768 bytes then av_free( buffer ) results
in a crash due to invalid free/delete (which can also be detected by
valgrind).
Not calling av_free( buffer ) leads to a memory leak (reported by valgrind).

In the case of calling av_free() Valgrind reports the buffer as
already being free‘d in:

==5471==  Address 0x9181680 is 0 bytes inside a block of size 32,784 free‘d
==5471==    at 0x4C2A82E: free (in
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5471==    by 0x712EC6F: av_free (mem.c:186)
==5471==    by 0x6DBEFC4: ffio_set_buf_size (aviobuf.c:707)
==5471==    by 0x6DBE1E5: fill_buffer (aviobuf.c:408)
==5471==    by 0x6DBE570: avio_read (aviobuf.c:495)
==5471==    by 0x6DE8971: ff_id3v2_read (id3v2.c:748)
==5471==    by 0x6EA4F42: avformat_open_input (utils.c:638)

which if you follow the call in a debugger leads to the culprit at
aviobuf.c:408:

    /* make buffer smaller in case it ended up large after probing */
    if (s->read_packet && s->buffer_size > max_buffer_size) {
        ffio_set_buf_size(s, max_buffer_size);

        s->checksum_ptr = dst = s->buffer;
        len = s->buffer_size;
    }

This only gets called when we are reading. So in the case of using
custom input libav takes it upon itself to tinker with the user
supplied buffer. The crash only occurs if the buffer size is larger
than 32KB
which in my case it was because I was trying to follow some examples
which show allocating (32768 + FF_INPUT_BUFFER_PADDING_SIZE) bytes.

I don‘t know if the bug is that libav is supposed to give an error if
the buffer is larger than 32KB, or not tinker with user supplied
buffers, or avio_alloc_context should take a ** to the buffer so it
can reallocate properly and clients don‘t have
to choose between a double free or a memory leak, but its definitely
wrong one way or another. I actually do not understand why the user
needs to pass in the buffer at all as it seems avio_alloc_context
could do it internally if it is going to
reallocate it on a whim anyway.

regards,
Mark

从这段描述中可以看出,当使用自定义输入的时候,如果iobuffer大于32KB就会在av_free(iobuffer)时导致段错误。这个问题甚是诡异啊。

ffmpeg : av_free段错误