AddressSanitizer: heap-use-after-free only on Release archive

764 Views Asked by At

I have created an example of my class: https://github.com/ChoadPet/H.264-Decoding

When I build my application with DEBUG configuration everything is working fine, but when I archive RELEASE it's crashing on this line:

let status = VTDecompressionSessionDecodeFrame(session,
                                               sampleBuffer: sampleBuffer,
                                               flags: defaultDecodeFlags,
                                               frameRefcon: nil,
                                               infoFlagsOut: nil)

With Address Sanitizer enable I got this error: Thread 9: Use of deallocated memory

SUMMARY: AddressSanitizer: heap-use-after-free
(.../Frameworks/libclang_rt.asan_ios_dynamic.dylib:arm64+0x1a1f4) in wrap_memmove
...
(if you need more crash info, let me know)

Without: Thread 12: EXC_BAD_ACCESS (code=1, address=0x107dd0020)


I do understand that there is some memory that was freed and it accesses by VTDecompressionSessionDecodeFrame method, but I can't find any address with hex, and I don't understand how this is working perfectly with the DEBUG build.
Before this method, session and sampleBuffer are successfully created(initialized).

Is there are some project settings I can change to DEBUG configuration which can cause the crash? Or somebody can point me out on a code issue?

Thank you!

2

There are 2 best solutions below

0
On BEST ANSWER

Changing Optimization Level for Release archive to the same as for Debug - No Optimization[-Onone] hide the problem, but changing build configuration is not the right way to resolve this kinda problem. Also, the problem was not exactly in sampleBuffer. The problem was in blockBufferOut parameter, which goes into sampleBuffer later. I will update the repo source code, so the community can see changes clearly.

So I had before this logic:

// 1. Creating blockBuffer from `bufferPointer`
localFrame.withUnsafeMutableBufferPointer { bufferPointer in
   // I should write everything in this body,
   // since bufferPointer would be released after the closure
   // and so, it will be released from bufferBlock
}

// 2. I called this method, which is creating `sampleBuffer`
CMSampleBufferCreateReady

// 3. I called this method, which is decode frame with session and sampleBuffer 
VTDecompressionSessionDecodeFrame

/* 
and on this line, it crashes with EXC_BAD_ACCESS, 
because the sample wasn't valid anymore, because 
on step 1, bufferPointer only valid inside body closure, 
so it's release after block when I created sampleBuffer
and later decode it.


This is even pointed by documentation:

Parameters

body
Closure with an UnsafeMutableBufferPointer parameter that points to the
contiguous storage for the array. If no such storage exists, it is created. If
the body has a return value, that value is also used as the return value for the
withUnsafeMutableBufferPointer(_:) method. The pointer argument is valid only for
the duration of the method’s execution.
*/

Summary: if you operate on bufferPointer, do all operations inside a closure.

0
On

Added to the answer provided by @vpoltave, I found using a dispatch queue after the samplebuffer creation used to give me an EXC_BAD_ACCESS error or if you turn on address sanitiser, then it would error out in the com.apple.coremedia.videomediaconverter with Use of deallocated memory. Suggestion is to enqueue the raw data instead of the created buffers. For me the source was a frame in elementary format coming in callbacks.