[FFmpeg-user] How to correctly free a double-linked list

Paul B Mahol onemda at gmail.com
Sun Jul 7 14:51:17 EEST 2019


On 7/7/19, Ulf Zibis <Ulf.Zibis at gmx.de> wrote:
>
> Am 07.07.19 um 12:42 schrieb Ulf Zibis:
>> Hi,
>>
>> when running my code, at the end I irregularly get messages like this:
>> [.....]
>> [Parsed_lineshiftrecover_0 @ 0x55e5afb83e80] start freeing memory ...
>> [Parsed_lineshiftrecover_0 @ 0x55e5afb83e80] filler and shifts freed!
>> [Parsed_lineshiftrecover_0 @ 0x55e5afb83e80] now start freeing
>> shifts_sums ...
>> corrupted double-linked list
>> debug/lineshiftrecover.sh: Zeile 99: 13359 Abgebrochen
>> (Speicherabzug geschrieben) ./ffmpeg -y -v warning -i debug/$sample -vf
>> lineshiftrecover${options[o]} -q 5 $output
>>
>> debug/lineshiftrecover.sh: Zeile 99: 10524 Abgebrochen
>> (Speicherabzug geschrieben) ./ffmpeg -y -v warning -i debug/$sample -vf
>> lineshiftrecover${options[o]} -q 5 $output
>>
>>
>> As you can see I'm running my code from the script
>> debug/lineshiftrecover.sh
>> lineshiftrecover is a new filter I'm working on. It's purpose is to
>> repair shifted line glitches in videos recoded from VHS tape.
>>
>> The code runs fine until I'm coming to free the allocated memory in
>> function "uninit". The code is:
>> static av_cold void uninit(AVFilterContext *ctx)
>> {
>>     LineShiftContext *s = ctx->priv;
>>     av_log(ctx, s->report >= R_SHIFTS ? AV_LOG_WARNING : AV_LOG_INFO,
>> "start freeing memory ...\n");
>>     for (int p = 0; p < s->nb_planes; p++)
>>         av_freep(&s->filler[p]);
>>     av_freep(&s->shifts);
>> /*
>>     printf("printf(): filler and shifts freed!\n");
>> */
>>     av_log(ctx, s->report >= R_SHIFTS ? AV_LOG_WARNING : AV_LOG_INFO,
>> "filler and shifts freed!\n");
>>     if (s->report >= R_SHIFTS) {
>> /*
>>         printf("do printf() before statistic of found shifts!\n");
>>         av_log(ctx, AV_LOG_WARNING, "statistic of found shifts ...\n");
>>         av_log(NULL, AV_LOG_WARNING, "shift:    "); // * increment);
>>         for (int shift = 0; shift <= s->span_r -  s->span_l; shift++)
>>             av_log(NULL, AV_LOG_WARNING, "%6d", s->span_l + shift);
>>         for (int l = 0; l <= s->lines; l++) {
>>             av_log(NULL, AV_LOG_WARNING, "\nline %4d:", s->start + l);
>>             for (int shift = 0; shift <= s->span_r -  s->span_l; shift++)
>>                 av_log(NULL, AV_LOG_WARNING, "%6d",
>> s->shifts_sums[l][shift]);
>>             av_log(NULL, AV_LOG_WARNING, "\n");
>>         }
>> */
>> /*
>>         printf("printf(): now start freeing shifts_sums ...\n");
>> */
>>         av_log(ctx, AV_LOG_WARNING, "now start freeing shifts_sums
>> ...\n");
>>         for (int l = 0; l <= s->lines; l++) {
>>             av_freep(&(s->shifts_sums[l]));
>>         }
>>         av_log(ctx, AV_LOG_WARNING, "lines of shifts_sums freed!\n");
>>         av_freep(&(s->shifts_sums));
>> /*
>>         printf("printf(): shifts_sums freed!\n");
>> */
>>         av_log(ctx, AV_LOG_WARNING, "shifts_sums freed!\n");
>>     }
>> }
>>
>> The out-commented printf() lines are to check if there is a problem if
>> the av_log print buffer is not flushed already, but this seems not the
>> case.
>>
>> The definition is:
>>     int16_t **shifts_sums;
>> The initialization is:
>> static int config_props(AVFilterLink *inlink)
>> {
>>     [.....]
>>     if (s->report >= R_SHIFTS) {
>>         s->shifts_sums = av_malloc((s->lines + 1) *
>> sizeof(*s->shifts_sums));
>>         for (int l = s->lines; l >= 0; l--) {
>>             s->shifts_sums[l] = av_malloc((s->span_r - s->span_l + 1) *
>> sizeof(**s->shifts_sums));
>>             memset(s->shifts_sums[l], 0, (s->span_r - s->span_l + 1) *
>> sizeof(**s->shifts_sums));
>>         }
>>     }
>> }
> Now I have added an additional log here:
>         for (int l = 0; l <= s->lines; l++) {
>             av_log(ctx, AV_LOG_WARNING, "freeing line %d ...\n", l);
>             av_freep(&(s->shifts_sums[l]));
>         }
>
> Sometimes I now get (there are 10 lines existing):
> [Parsed_lineshiftrecover_0 @ 0x560c176b6e80] start freeing memory ...
> [Parsed_lineshiftrecover_0 @ 0x560c176b6e80] filler and shifts freed!
> [Parsed_lineshiftrecover_0 @ 0x560c176b6e80] now start freeing
> shifts_sums ...
> [Parsed_lineshiftrecover_0 @ 0x560c176b6e80] freeing line 0 ...
> [Parsed_lineshiftrecover_0 @ 0x560c176b6e80] freeing line 1 ...
> [Parsed_lineshiftrecover_0 @ 0x560c176b6e80] freeing line 2 ...
> [Parsed_lineshiftrecover_0 @ 0x560c176b6e80] freeing line 3 ...
> corrupted double-linked list
> debug/lineshiftrecover.sh: Zeile 99: 16389 Abgebrochen
> (Speicherabzug geschrieben) ./ffmpeg -y -v warning -i debug/$sample -vf
> lineshiftrecover${options[o]} -q 5 $output
>
> ... but sometimes only:
> [Parsed_lineshiftrecover_0 @ 0x560c176b6e80] start freeing memory ...
> corrupted double-linked list
> debug/lineshiftrecover.sh: Zeile 99: 16389 Abgebrochen
> (Speicherabzug geschrieben) ./ffmpeg -y -v warning -i debug/$sample -vf
> lineshiftrecover${options[o]} -q 5 $output
>
> Weird random result! I don't get a clue whats the cause for the error.

You need to memset/av_calloc array after allocation that hold pointers to lines.
Otherwise you use uninitialized memory.

If you can, install and use valgrind to help you debug such problems.


>
> Please help,
>
> -Ulf
>
> _______________________________________________
> ffmpeg-user mailing list
> ffmpeg-user at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-user
>
> To unsubscribe, visit link above, or email
> ffmpeg-user-request at ffmpeg.org with subject "unsubscribe".


More information about the ffmpeg-user mailing list