Search code examples
iosobjective-cexc-bad-access

EXC_BAD_ACCESS when passing a parameter in dispatch_async in objective-C


I pass a variable to another method. when accessing this property app crashes with EXC_BAD_ACCESS error.

   in class1: 
  CVPixelBufferRef pixelBuffer;
  @implementation class1
     - (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
        pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
        dispatch_async( dispatch_get_main_queue(), ^{
           predictions = [dTFG runX:pixelBuffer orientation: UIDeviceOrientationPortrait CardRect: _vwRect];

       }
     }
   } 

    in class2:
    - (NSArray*) runX:(CVPixelBufferRef) pixelBuffer orientation: (UIDeviceOrientation) orientation CardRect:(CGRect) CardRect {
       CFRetain(pixelBuffer);  // Error: Thread 1: EXC_BAD_ACCESS (code=1, address=0x800000060)
    }

Thread 1: EXC_BAD_ACCESS (code=1, address=0x800000060)

When I commented dispatch_async, crash not happened.

According to another answer, this error is (probably) because of released object. but why is it released in this situation but without dispatch_async, it is not released.


Solution

  • The CVImageBufferRef returned by CMSampleBufferGetImageBuffer() isn't an object, it's just a C structure, so it won't participate in reference counting. If you're going to pass it into a block that runs asynchronously, you need to ensure that that data remains valid. Notice that the documentation tells you specifically:

    The caller does not own the returned buffer, and must retain it explicitly if the caller needs to maintain a reference to it.

    I haven't dug too far into it, but given the data type that probably means that you need to call CVBufferRetain() on pixelBuffer (and then CVBufferRelease() when you're done with it).