it-swarm.com.ru

Понимание ошибки glibc "поврежденный размер против prev_size"

Я внедрил мост JNA в FDK-AAC. Исходный код можно найти в здесь

При проведении бенчмаркинга моего кода я могу получить сотни успешных запусков на одном входе, а затем иногда сбой на уровне C, который уничтожит весь процесс, вызывая создание дампа ядра:

Глядя на дамп ядра, это выглядит так:

#1  0x00007f3e92e00f5d in __GI_abort () at abort.c:90
#2  0x00007f3e92e4928d in __libc_message ([email protected]=do_abort, [email protected]=0x7f3e92f70528 "*** Error in `%s': %s: 0x%s ***\n") at ../sysdeps/posix/libc_fatal.c:181
#3  0x00007f3e92e5064a in malloc_printerr (action=<optimized out>, str=0x7f3e92f6cdee "corrupted size vs. prev_size", ptr=<optimized out>, ar_ptr=<optimized out>) at malloc.c:5426
#4  0x00007f3e92e5304a in _int_free (av=0x7f3de0000020, p=<optimized out>, have_lock=0) at malloc.c:4337
#5  0x00007f3e92e5744e in __GI___libc_free (mem=<optimized out>) at malloc.c:3145
#6  0x00007f3e113921e9 in FDKfree (ptr=0x7f3de009df60) at libSYS/src/genericStds.cpp:233
#7  0x00007f3e1130d7d3 in Free_AacEncoder (p=0x7f3de0115740) at libAACenc/src/aacenc_lib.cpp:407
#8  0x00007f3e1130fbb3 in aacEncClose (phAacEncoder=0x7f3de0115740) at libAACenc/src/aacenc_lib.cpp:1395

Эта ошибка трассировки обратно/стек воспроизводима, если я запускаю повторный тест достаточно много раз, хотя мне трудно понять, что может быть причиной такой ошибки? Память выделена для указателя 0x7f3de009df60 также размещается внутри кода CPP/C, и я могу гарантировать, что освобождается тот же самый экземпляр, который был выделен. Тест, конечно, однопоточный.

Прочитав это:

проверки безопасности && внутренние функции

Мне все еще трудно понять - какой может быть реальный (не эксплуатируемый, а скорее ошибочный) сценарий, который заставляет меня получить вышеуказанную ошибку? и почему это происходит очень редко?

Текущее подозрение :

Запустив подробную трассировку, я получаю следующие данные:

#0  __GI_raise ([email protected]=6) at ../sysdeps/unix/sysv/linux/raise.c:51
        set = {__val = {4, 6378670679680, 645636045657660056, 90523359816, 139904561311072, 292199584, 139903730612120, 139903730611784, 139904561311088, 1460617926600, 47573685816, 4119199860131166208, 
            139904593745464, 139904553224483, 139904561311136, 288245657}}
        pid = <optimized out>
        tid = <optimized out>
#1  0x00007f3e92e00f5d in __GI_abort () at abort.c:90
        save_stage = 2
        act = {__sigaction_handler = {sa_handler = 0x7f3de026db10, sa_sigaction = 0x7f3de026db10}, sa_mask = {__val = {139903730540556, 19, 30064771092, 812522497172832284, 139903728706672, 1887866374039011357, 
              139900298780168, 3775732748407067896, 763430436865, 35180077121538, 4119199860131166208, 139904561311552, 139904553065676, 1, 139904561311584, 139904561312192}}, sa_flags = 4096, 
          sa_restorer = 0x14}
        sigs = {__val = {32, 0 <repeats 15 times>}}
#2  0x00007f3e92e4928d in __libc_message ([email protected]=do_abort, [email protected]=0x7f3e92f70528 "*** Error in `%s': %s: 0x%s ***\n") at ../sysdeps/posix/libc_fatal.c:181
        ap = {{gp_offset = 40, fp_offset = 32574, overflow_arg_area = 0x7f3e11adf1d0, reg_save_area = 0x7f3e11adf160}}
        fd = <optimized out>
        list = <optimized out>
        nlist = <optimized out>
        cp = <optimized out>
        written = <optimized out>
#3  0x00007f3e92e5064a in malloc_printerr (action=<optimized out>, str=0x7f3e92f6cdee "corrupted size vs. prev_size", ptr=<optimized out>, ar_ptr=<optimized out>) at malloc.c:5426
        buf = "00007f3de009e9f0"
        cp = <optimized out>
        ar_ptr = <optimized out>
        ptr = <optimized out>
        str = 0x7f3e92f6cdee "corrupted size vs. prev_size"
        action = <optimized out>
#4  0x00007f3e92e5304a in _int_free (av=0x7f3de0000020, p=<optimized out>, have_lock=0) at malloc.c:4337
        size = 2720
        fb = <optimized out>
        nextchunk = 0x7f3de009e9f0
        nextsize = 736
        nextinuse = <optimized out>
        prevsize = <optimized out>
        bck = <optimized out>
        fwd = <optimized out>
        errstr = 0x0
        locked = <optimized out>
#5  0x00007f3e92e5744e in __GI___libc_free (mem=<optimized out>) at malloc.c:3145
        ar_ptr = <optimized out>
        p = <optimized out>
        hook = <optimized out>
#6  0x00007f3e113921e9 in FDKfree (ptr=0x7f3de009df60) at libSYS/src/genericStds.cpp:233
No locals.
#7  0x00007f3e1130d7d3 in Free_AacEncoder (p=0x7f3de0115740) at libAACenc/src/aacenc_lib.cpp:407
No locals.
#8  0x00007f3e1130fbb3 in aacEncClose (phAacEncoder=0x7f3de0115740) at libAACenc/src/aacenc_lib.cpp:1395
        hAacEncoder = 0x7f3de009df60
        err = AACENC_OK
  • В кадре # 6 вы можете увидеть указатель в вопросах 0x7f3de009df60.
  • В кадре # 4 вы можете видеть, что размер равен 2720, что действительно является ожидаемым размером освобождаемой структуры.
  • Однако адрес nextchunk равен 0x7f3de009e9f0, что составляет всего 2704 байта после текущего указателя, который освобождается.
  • Я могу подтвердить, что это всегда тот случай, когда ошибка воспроизводится.
  • Может ли это быть явным признаком ошибки, с которой я сталкиваюсь ??
13
Sheinbergon

Итак, мне удалось преодолеть эту проблему.

Во-первых, практическая причина "поврежденный размер по сравнению с prev_size" довольно проста - поля структуры управления блоками памяти в соседнем следующем блоке перезаписываются из-за неконкурентного доступа кода. если вы выделите x байтов для указателя p, но завершите запись за пределы x в отношении того же указателя, вы можете получить эту ошибку, указывающую текущее выделение памяти (чанк) размер не совпадает с тем, что находится в следующей структуре элемента управления чанком (из-за того, что он перезаписывается).

Что касается причины этой утечки памяти - отображение структуры, выполненное на уровне Java/JNA, подразумевает разные #pragma связанные отступы/выравнивание из того, с чем была скомпилирована dll/so. Это, в свою очередь, привело к записи данных за пределы выделенной структуры. Отключение этого выравнивания заставило проблемы исчезнуть. (Тысячи казней без единой аварии!).

19
Sheinbergon