Search code examples
iosswiftmemoryvideo-toolbox

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


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!


Solution

  • 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.