web-dev-qa-db-fra.com

Comprendre "erreur de taille corrompue vs prev_size" glibc

J'ai mis en place un pont entre la JNA et le FDK-AAC. Le code source peut être trouvé dans ici

Lors de l'analyse comparative de mon code, je peux obtenir des centaines d'exécutions réussies sur la même entrée, puis occasionnellement un blocage au niveau C qui va tuer l'ensemble du processus, ce qui entraîne la génération d'un vidage de la mémoire:

En regardant le core dump, cela ressemble à ceci:

#1  0x00007f3e92e00f5d in __GI_abort () at abort.c:90
#2  0x00007f3e92e4928d in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=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

Cette erreur de trace de pile/retour est reproductible si je répète le test de performance suffisamment de fois, même si j'ai du mal à comprendre quelle peut être la cause de cette erreur. Mémoire allouée au pointeur 0x7f3de009df60 est également alloué dans le code CPP/C et je peux garantir que la même instance allouée est en cours de libération. La référence est, bien sûr - mono-thread.

Après avoir lu ces:

contrôles de sécurité && fonctions internes

J'ai encore du mal à comprendre - quel pourrait être un scénario réel (de non-exploitation, mais plutôt d'erreur) qui me fait obtenir l'erreur ci-dessus? et pourquoi cela arrive t-il à peine?

Soupçons actuels :

En effectuant une trace détaillée, je reçois cette entrée:

#0  __GI_raise (sig=sig@entry=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 (action=action@entry=do_abort, fmt=fmt@entry=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
  • Dans le cadre # 6 , vous pouvez voir le pointeur dans les questions est 0x7f3de009df60.
  • Dans le cadre # 4 , vous pouvez voir que la taille est 2720, ce qui correspond bien à la taille attendue de la structure libérée.
  • Cependant, l'adresse de nextchunk est 0x7f3de009e9f0, qui ne fait que 2704 octets après le pointeur actuel qui est libéré.
  • Je peux confirmer que c'est toujours le cas lorsque l'erreur se reproduit.
  • Serait-ce une indication forte de l'erreur à laquelle je suis confronté?
13
Sheinbergon

OK, alors j'ai réussi à surmonter ce problème.

Tout d'abord - Une cause pratique de "taille corrompue par rapport à prev_size" est assez simple - les champs de structure de contrôle de bloc de mémoire dans le bloc suivant adjacent sont écrasés en raison d'un accès hors limites par le code. si vous allouez x octets pour le pointeur p mais que vous finissiez par écrire au-delà de x en ce qui concerne le même pointeur, vous pourriez avoir cette erreur, indiquant l'allocation de mémoire actuelle (morceau) la taille n'est pas identique à celle trouvée dans la structure de contrôle de bloc suivante (en raison de son écrasement).

En ce qui concerne la cause de cette fuite de mémoire, le mappage de structure effectué dans la couche Java/JNA impliquait un remplissage/alignement lié #pragma Lié à celui avec lequel dll/so a été compilé. À son tour, les données ont été écrites au-delà de la limite de structure allouée. Désactiver cet alignement a fait disparaître les problèmes. (Des milliers d'exécutions sans un seul crash!).

19
Sheinbergon