[FFmpeg-devel] [PATCH] Fix for rc_eq memory leak
Stefano Sabatini
stefano.sabatini-lala
Mon Aug 4 23:11:54 CEST 2008
On date Monday 2008-08-04 11:42:02 -0700, Art Clarke encoded:
> On Sat, Aug 2, 2008 at 4:46 AM, Stefano Sabatini <
> stefano.sabatini-lala at poste.it> wrote:
> > On date Thursday 2008-07-31 11:21:45 -0700, Art Clarke encoded:
[...]
> > > Index: libavformat/utils.c
> > > ===================================================================
> > > --- libavformat/utils.c (revision 14487)
> > > +++ libavformat/utils.c (working copy)
> > > @@ -2212,6 +2212,7 @@
> > > }
> > > av_free(st->index_entries);
> > > av_free(st->codec->extradata);
> > > + av_free(st->codec->rc_eq);
> > > av_free(st->codec);
> > > av_free(st->filename);
> > > av_free(st->priv_data);
> >
> > No this shouldn't be necessary anymore since r14260, unless you still
> > didn't already close all the codecs with avcodec_close(), which I
> > think is *required* by the current API.
> >
> > (BTW currently avcodec_close() doesn't free extradata, I think this is a
> > memleak, also it could be a good idea to use av_freep() rather than
> > av_free() to save some SIGSEGV.)
> >
> > For example ffmpeg.c does exactly this, it closes all the decoders
> > before to call av_close_input_stream().
> >
> > Maybe a better solution would be to do call avcodec_close() in
> > av_close_input_stream(), at least conditionally, for example:
> >
> > if(st->codec->codec) /* already closed or never opened */
> > avcodec_close(st->codec);
> >
> > This looks like a better solution because it would simplify ffmpeg.c
> > (and others applications as well).
> >
> > In the case of ffmpeg.c this could eliminate the need for the loop:
> > for(i=0;i<nb_istreams;i++) {
> > ist = ist_table[i];
> > if (ist->decoding_needed) {
> > avcodec_close(ist->st->codec);
> > }
> > }
> >
> > at the end of av_encode().
> >
> > Opinions?
[...]
> Good point; The problem here is that to generate the leak, the test program
> doesn't need to open a codec. Many formats (e.g. FLV) will open a code
> behind the scenes when av_find_stream_info(context) is called.
>
> Try compiling the attached test program, and then passing in an FLV file for
> input. You'll see the source code is a well behaved
> libav* program, closing up after itself.
>
> That's why I put the change I put in in where I did (using an av_free() call
> rather than av_freep to stay with the conventions in that code). In some
> cases the user will have called avcodec_close because they opened the codec,
> in which case "rc_eq" will be null and av_free is safe. If they haven't
> called avcodec_close, because they didn't open the codec (e.g.
> av_find_stream_info actually opened the codec), then we free it then.
>
> As for the memory leak in avcodec_close on 'extradata', it does look like
> you're right, but I don't have a test case that shows it (hence I'm not
> patching that ) :) If anyone can suggest a good test case, and or provide a
> file, I'll add it to our test suite and create a patch.
>
> Given that argument, are you OK with the patch?
I continue to insist with a different solution, according to me we
should close the codecs even jsut after we call
av_input_find_stream_info(), having duplicated the same code in
avcodec_close() and av_close_input_stream() doesn't look like a
particularly good idea.
Said that I'm not a maintainer of anything so I can just express my
opinion but I have no final word.
As for an alternative solution, I started to hack a solution, then I
got stuck with some extradata related SIGSEGVs, so I left it apart,
I'll hopefully come back to it in some time.
> - Art
> #include <stdio.h>
> #include <libavformat/avformat.h>
>
> int
> main(int argc, char**argv)
> {
> AVFormatContext* context=0;
> int retval = -1;
> const char* filename = 0;
>
> /*
> int blah;
> if (blah == 2)
> {
> printf("this should give a valgrind error");
> }
> */
>
> if (argc != 2 || !argv[1] || !*argv[1])
> {
> printf("no input file specified\n");
> return -1;
> }
> filename = argv[1];
>
> av_register_all();
>
> retval = av_open_input_file(&context, filename, NULL, 0, NULL);
> if (retval < 0)
> {
> printf("cannot open input file: %s\n", filename);
> return -1;
> }
>
> retval = av_find_stream_info(context);
> if (retval < 0)
> {
> printf("cannot find information about streams in: %s\n",
> filename);
> return -1;
> }
>
> dump_format(context, 0, filename, 0);
>
> av_close_input_file(context);
> if (retval < 0)
> {
> printf("cannot close file: %s\n", filename);
> return -1;
> }
> return 0;
> }
Regards.
--
FFmpeg = Frenzy Fantastic Maxi Pitiless Elastic God
More information about the ffmpeg-devel
mailing list