Ik heb een JNA-brug naar FDK-AAC geïmplementeerd. De broncode is hier
te vinden
Bij het benchmarken van mijn code kan ik honderden succesvolle runs op dezelfde invoer krijgen, en dan af en toe een C-level crash die het hele proces doodt, waardoor een core-dump wordt gegenereerd:
Als je naar de kerndump kijkt, ziet het er als volgt uit:
#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
Deze back/stack trace-fout is reproduceerbaar als ik de benchmark vaak genoeg herhaal, hoewel ik het moeilijk vind om te begrijpen wat de oorzaak van een dergelijke fout kan zijn? Geheugen toegewezen aan pointer 0x7f3de009df60
wordt ook toegewezen binnen de CPP/C-code en ik kan garanderen dat dezelfde instantie die is toegewezen, wordt vrijgegeven. De benchmark is natuurlijk – single-threaded.
Na het lezen van deze:
veiligheidscontroles & amp; & amp;
interne functies
Ik ben nog steeds een harde tijd begrip – wat misschien wel een echte (niet-uitbuiting, maar eerder fout)) scenario dat me zorgt ervoor dat de bovenstaande fout te krijgen? en waarom gebeurt het zeer nauwelijks?
Huidige vermoeden
Het runnen van een gedetailleerde backtrace, krijg ik deze ingang:
#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
- In frame #6zie je dat de aanwijzer in vragen
0x7f3de009df60
is. - In frame #4kun je zien dat de grootte 2720 is, wat inderdaad de verwachte grootte is van de structuur die wordt vrijgegeven.
- Het adres van
nextchunk
is echter0x7f3de009e9f0
, wat slechts 2704 bytes is na de huidige pointer die wordt vrijgegeven. - Ik kan bevestigen dat dit altijd het geval is wanneer de fout zich herhaalt.
- Kan dit een sterke indicatie zijn van de fout die ik tegenkom ??
Antwoord 1, autoriteit 100%
OK, dus ik heb dit probleem kunnen oplossen.
Allereerst – Een praktische oorzaak voor “corrupte size vs. prev_size” is vrij eenvoudig: de besturingsstructuurvelden van de geheugenbrok in de aangrenzende volgende chunk worden overschreven vanwege toegang buiten het bereik van de code. als u x
bytes toewijst voor pointer p
maar eindigt met schrijven voorbij x
met betrekking tot dezelfde pointer, kunt u deze fout krijgen, die de de huidige grootte van de geheugentoewijzing (chunk) is niet hetzelfde als wat wordt gevonden in de volgende chunk-besturingsstructuur (omdat deze wordt overschreven).
Wat de oorzaak van dit geheugenlek betreft: structuurtoewijzing in de Java/JNA-laag impliceerde een andere #pragma
-gerelateerde opvulling/uitlijning dan waarmee dll/so was gecompileerd. Dit zorgde er op zijn beurt voor dat gegevens buiten de toegewezen structuurgrens werden geschreven. Door die uitlijning uit te schakelen, verdwenen de problemen. (Duizenden executies zonder een enkele crash!).