Always ensure proper exception safety by placing cleanup code in @finally blocks, using stack-allocated exceptions, and implementing comprehensive exception handling for different types. Resource cleanup must occur even when exceptions are thrown to prevent memory leaks.

Key practices:

Example:

@try {
  [inv invokeWithTarget:strongModule];
} @catch (NSException *exception) {
  caughtException = maybeCatchException(shouldCatchException, exception);
} @catch (NSError *error) {
  caughtException = maybeCatchException(shouldCatchException, error);
} @finally {
  [retainedObjectsForInvocation removeAllObjects]; // Always cleanup
}

// For C++ exceptions, use stack allocation
throw std::runtime_error("Error message");

This ensures robust error handling while preventing resource leaks and maintaining proper exception semantics.