Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Smart Debugging - Heavy Weapons for Hard Bugs

Smart Debugging - Heavy Weapons for Hardย Bugs

Debugging can be exciting, but often also very, very frustrating. In this talk, I'll show you some lesser-known tools and techniques to find problems faster and make the compiler show you issues, before they become a crash for your users. Of course we also look at some real world examples.. TEKI CON๐Ÿ Atlanta, March 2018

Video and Blog Post coming up soon at https://pspdfkit.com/blog/

Avatar for Peter Steinberger

Peter Steinberger

March 12, 2018
Tweet

More Decks by Peter Steinberger

Other Decks in Programming

Transcript

  1. Categories of Bugs โ†’ Business Logic โ†’ Performance โ†’ API

    Misuse โ†’ View โ†’ Memory โ†’ Locking/Threading/Races Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  2. Categories of Bugs โ†’ Business Logic Tests โ†’ Performance โ†’

    API Misuse โ†’ View โ†’ Memory โ†’ Locking/Threading/Races Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  3. Categories of Bugs โ†’ Business Logic Tests โ†’ Performance โžก

    Instruments + Measure โ†’ API Misuse โ†’ View โ†’ Memory โ†’ Locking/Threading/Races Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  4. Categories of Bugs โ†’ Business Logic Tests โ†’ Performance โžก

    Instruments + Measure โ†’ API Misuse โžก Documentation + Asserts โ†’ View โ†’ Memory โ†’ Locking/Threading/Races Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  5. Categories of Bugs โ†’ Business Logic Tests โ†’ Performance โžก

    Instruments + Measure โ†’ API Misuse โžก Documentation + Asserts โ†’ View โžก Architecture, UI Tests, QA โ†’ Memory โ†’ Locking/Threading/Races Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  6. Debug for any ObjC Object @interface NSObject (Private) -(id)_ivarDescription; -(id)_shortMethodDescription;

    -(id)_methodDescription; @end Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  7. LLDB View Debugging po [UIWindow.keyWindow recursiveDescription] po [UIViewController _printHierarchy] po

    [UIView _autolayoutTrace] po [_UIViewLayoutFeedbackLoopDebugger layoutFeedbackLoopDebugger] // lldb in Swift context: expr -l objc++ -O -- [UIWindow.keyWindow recursiveDescription] Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  8. View Debugging Helper Category @interface UIView (Debug) - (id)recursiveDescription; @end

    po self.recursiveDescription() as NSString Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  9. .lldbinit command alias alt expr -l objc++ -O --[[UIWindow keyWindow]

    _autolayoutTrace] Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  10. github.com/facebook/chisel Command Explanation pa11y <aView> Print accessibility labels alamborder Highlight

    views with ambiguous layout pproperties Print the properties of an instance slowanim Slows down animations. Sim + Device showimage Open a UIImage in Preview.app pactions <control> Print the actions/targets of a control Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  11. ๏ฌndinstances findinstances UIView subviews.@count == 0 findinstances NSArray @count >

    100 findinstances UIScrollViewDelegate findinstances UIView window == nil || hidden == true || alpha == 0 || layer.bounds.#size.width == 0 || layer.bounds.#size.height == 0 Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  12. ๏ฌndinstances findinstances UIView subviews.@count == 0 findinstances NSArray @count >

    100 findinstances UIScrollViewDelegate findinstances UIView window == nil || hidden == true || alpha == 0 || layer.bounds.#size.width == 0 || layer.bounds.#size.height == 0 Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  13. ๏ฌndinstances findinstances UIView subviews.@count == 0 findinstances NSArray @count >

    100 findinstances UIScrollViewDelegate findinstances UIView window == nil || hidden == true || alpha == 0 || layer.bounds.#size.width == 0 || layer.bounds.#size.height == 0 Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  14. ๏ฌndinstances findinstances UIView subviews.@count == 0 findinstances NSArray @count >

    100 findinstances UIScrollViewDelegate findinstances UIView window == nil || hidden == true || alpha == 0 || layer.bounds.#size.width == 0 || layer.bounds.#size.height == 0 Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  15. clang -cc1 -analyzer-checker-help Checker Explanation alpha.core.BoolAssignment Warn about assigning non-{0,1}

    values to Boolean variables alpha.clone.CloneChecker Reports similar pieces of code alpha.cplusplus.MisusedMovedObject Method calls on a moved-from object and copying a moved-from object will be reported optin.osx.cocoa.localizability.NonLocalizedStri ngChecker Warns about uses of non-localized NSStrings passed to UI methods expecting localized NSStrings Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  16. PSPDF_ANALYZER_FLAGS = -Xclang -analyzer-checker -Xclang alpha.core.BoolAssignment -Xclang -analyzer-checker -Xclang alpha.core.CallAndMessageUnInitRefArg

    -Xclang -analyzer-checker -Xclang alpha.core.DynamicTypeChecker -Xclang -analyzer-checker -Xclang alpha.core.FixedAddr -Xclang -analyzer-checker -Xclang alpha.core.IdenticalExpr -Xclang -analyzer-checker -Xclang alpha.core.PointerSub -Xclang -analyzer-checker -Xclang alpha.core.SizeofPtr -Xclang -analyzer-checker -Xclang alpha.core.TestAfterDivZero -Xclang -analyzer-checker -Xclang alpha.security.ArrayBoundV2 -Xclang -analyzer-checker -Xclang alpha.security.MallocOverflow -Xclang -analyzer-checker -Xclang alpha.security.ReturnPtrRange -Xclang -analyzer-checker -Xclang alpha.security.taint.TaintPropagation -Xclang -analyzer-checker -Xclang alpha.cplusplus.MisusedMovedObject -Xclang -analyzer-checker -Xclang alpha.unix.BlockInCriticalSection -Xclang -analyzer-checker -Xclang alpha.unix.Chroot -Xclang -analyzer-checker -Xclang alpha.unix.SimpleStream -Xclang -analyzer-checker -Xclang alpha.unix.cstring.BufferOverlap -Xclang -analyzer-checker -Xclang alpha.unix.cstring.NotNullTerminated -Xclang -analyzer-checker -Xclang alpha.unix.cstring.OutOfBounds -Xclang -analyzer-checker -Xclang alpha.osx.cocoa.InstanceVariableInvalidation -Xclang -analyzer-checker -Xclang alpha.osx.cocoa.DirectIvarAssignmentForAnnotatedFunctions -Xclang -analyzer-checker -Xclang alpha.core.Conversion // Crashes Xcode 9.2 // -Xclang -analyzer-checker -Xclang alpha.cplusplus.IteratorPastEnd Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  17. #ifndef __clang_analyzer__ // Ignore in analyzer - we're assigning nil

    to a nonnull property. // The getter never returns nil - we reload on demand. _resourceManager = nil; #endif Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  18. /** Returns the string argument marked as localized to avoid

    analyzer warnings. Use this for strings that may be shown in the UI but should not be localized. http://clang-analyzer.llvm.org/faq.html */ __attribute__((annotate("returns_localized_nsstring"))) inline NSString *PSPDFLocalizationNotNeeded(NSString *string) { return string; } Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  19. Warnings (Reality) // Xcode 9.2 PSPDF_WARNING_CFLAGS_0920 = $(inherited) $(PSPDF_ANALYZER_FLAGS) -Weverything

    -Wno-error-deprecated-declarations -Wno-objc-missing-property-synthesis -Wno-unused-parameter -Wno-covered-switch-default -Wno-direct-ivar-access -Wno-assign-enum -Wno-float-equal -Wno-vla -Wno-documentation-unknown-command -Wno-packed -Wno-padded -Wno-auto-import -Wno-selector -Wno-sign-conversion -Wno-auto-import -Wno-static-in-inline -Wno-gnu-conditional-omitted-operand -Wno-gnu-zero-variadic-macro-arguments -Wno-gnu-statement-expression -Wno-language-extension-token -Wno-pointer-arith -Wno-empty-translation-unit -Wno-format-non-iso -Wno-comment -Wno-gnu-folding-constant -Wno-c++98-compat-pedantic -Wno-c++98-compat -Wno-old-style-cast -Wno-incomplete-module -Wno-vla-extension -Wno-c99-extensions -Wno-cstring-format-directive -Rno-module-build -Wno-reserved-id-macro -Wno-undef -Wno-weak-vtables -Wno-over-aligned -Wno-double-promotion -Wno-incompatible-sysroot -Wno-gnu-auto-type -Wno-undefined-func-template -Wno-comma -Wno-c++1z-extensions // Xcode 9.3 PSPDF_WARNING_CFLAGS_0930 = $(PSPDF_WARNING_CFLAGS_0920) -Wno-zero-as-null-pointer-constant -Wno-deprecated-dynamic-exception-spec -Wno-private-module PSPDF_WARNING_CFLAGS = $(PSPDF_WARNING_CFLAGS_$(XCODE_VERSION_MINOR)) WARNING_CFLAGS = $(PSPDF_WARNING_CFLAGS) Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  20. Warnings (Reality) // Xcode 9.2 PSPDF_WARNING_CFLAGS_0920 = $(inherited) $(PSPDF_ANALYZER_FLAGS) -Weverything

    -Wno-error-deprecated-declarations -Wno-objc-missing-property-synthesis -Wno-unused-parameter -Wno-covered-switch-default -Wno-direct-ivar-access -Wno-assign-enum -Wno-float-equal -Wno-vla -Wno-documentation-unknown-command -Wno-packed -Wno-padded -Wno-auto-import -Wno-selector -Wno-sign-conversion -Wno-auto-import -Wno-static-in-inline -Wno-gnu-conditional-omitted-operand -Wno-gnu-zero-variadic-macro-arguments -Wno-gnu-statement-expression -Wno-language-extension-token -Wno-pointer-arith -Wno-empty-translation-unit -Wno-format-non-iso -Wno-comment -Wno-gnu-folding-constant -Wno-c++98-compat-pedantic -Wno-c++98-compat -Wno-old-style-cast -Wno-incomplete-module -Wno-vla-extension -Wno-c99-extensions -Wno-cstring-format-directive -Rno-module-build -Wno-reserved-id-macro -Wno-undef -Wno-weak-vtables -Wno-over-aligned -Wno-double-promotion -Wno-incompatible-sysroot -Wno-gnu-auto-type -Wno-undefined-func-template -Wno-comma -Wno-c++1z-extensions // Xcode 9.3 PSPDF_WARNING_CFLAGS_0930 = $(PSPDF_WARNING_CFLAGS_0920) -Wno-zero-as-null-pointer-constant -Wno-deprecated-dynamic-exception-spec -Wno-private-module PSPDF_WARNING_CFLAGS = $(PSPDF_WARNING_CFLAGS_$(XCODE_VERSION_MINOR)) WARNING_CFLAGS = $(PSPDF_WARNING_CFLAGS) Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  21. #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" ...

    #pragma clang diagnostic pop Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  22. Clang Sanitizers โ†’ Address Sanitizer โ†’ Unde๏ฌned Behaviour Sanitizer โ†’

    Main Thread Checker โ†’ Thread Sanitizer Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  23. Address Sanitizer /** ASAN_OPTIONS no longer settable when running tests

    within Xcode. rdar://28103342 Document Xcode config settings to enable Clang Sanitizers. rdar://28250805 Build fails with address sanitizer feature enabled and custom CC. rdar://24972653 https://github.com/google/sanitizers/wiki/AddressSanitizer */ __attribute__((visibility("default"))) __attribute__((no_sanitize_address)) FOUNDATION_EXPORT const char *__asan_default_options(void); FOUNDATION_EXPORT const char *__asan_default_options(void) { return "verbosity=0:detect_odr_violation=0:suppressions=" ASANSUPPPATH; // AddressSanitizerSuppressions.supp } __attribute__((constructor)) static void PSPDFASANSettingsPrinter(void) { NSLog(@"AddressSanitizer Enabled. Settings: %s (See ASAN_OPTIONS.h)", __asan_default_options()); } // FILE AddressSanitizerSuppressions.supp # Apple has issues in there that we cannot fix. interceptor_via_fun:pdf_Finalize Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  24. // We only enable ASAN for 64-bit as the Simulator

    has troubles running that in 32 bit. // We eventually run out of memory while the tests work. // Using ASAN on devices fails with "dyld: Library not loaded: @rpath/libclang_rt.asan_ios_dynamic.dylib". CLANG_ADDRESS_SANITIZER[arch=x86_64] = YES CLANG_UNDEFINED_BEHAVIOR_SANITIZER = YES // Typical slowdown introduced by ThreadSanitizer is about 5x-15x. // Typical memory overhead introduced by ThreadSanitizer is about 5x-10x. ENABLE_THREAD_SANITIZER = NO Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  25. Hunting an Over-Release *** -[PSPDFDocument release]: message sent to deallocated

    instance 0x617000007780 Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  26. // release resources as we no longer need them //

    but don't block the calling thread for this! [[PSPDFDispatchQueue.backgroundQueue namedQueue:@"cache.deallocation"] async:^{ @synchronized(self) { self->_imageRenderingCompletionBlock = nil; } }]; Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  27. Retain Tracker - (BOOL)shouldPrintRetainRelease { return !NSThread.isMainThread; } - (id)retain

    { // release, autorelease if ([self shouldPrintRetainRelease]) { printf("RETAIN %p %s (queue:%s) -> %s", (void *)self, NSThread.currentThread.name.UTF8String, [self queueName], [NSThread callStackSymbols].description.UTF8String); } return [super retain]; } Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  28. /** * Sets the superclass of a given class. *

    * @param cls The class whose superclass you want to set. * @param newSuper The new superclass for cls. * * @return The old superclass for cls. * * @warning You should not use this function. */ OBJC_EXPORT Class _Nonnull class_setSuperclass(Class _Nonnull cls, Class _Nonnull newSuper) __OSX_DEPRECATED(10.5, 10.5, "not recommended") __IOS_DEPRECATED(2.0, 2.0, "not recommended") __TVOS_DEPRECATED(9.0, 9.0, "not recommended") __WATCHOS_DEPRECATED(1.0, 1.0, "not recommended") __BRIDGEOS_DEPRECATED(2.0, 2.0, "not recommended"); Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  29. )AUTORELEASE 0x617000007780 (queue:com.apple.root.background-qos) -> ( 0 PSPDFKit 0x000000012ed5818b -[PSPDFRetainTracker autorelease]

    + 747 1 PSPDFKit 0x0000000129fbce4c _ZN5PSPDF2asI13PSPDFDocumentEEPT_P11objc_object + 652 2 PSPDFKit 0x0000000129fb83e3 _ZN5PSPDF11as_force_nnI13PSPDFDocumentEEPT_P8NSObject + 2563 3 PSPDFKit 0x0000000129fb8b02 -[PSPDFCacheDocumentHashManager willCloseDocument:] + 514 4 CoreFoundation 0x000000010feb2b8c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12 5 CoreFoundation 0x000000010feb2a65 _CFXRegistrationPost + 453 6 CoreFoundation 0x000000010feb27a1 ___CFXNotificationPost_block_invoke + 225 7 CoreFoundation 0x000000010fe74422 -[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1826 8 CoreFoundation 0x000000010fe735a1 _CFXNotificationPost + 609 9 Foundation 0x000000010eef2e57 -[NSNotificationCenter postNotificationName:object:userInfo:] + 66 10 PSPDFKit 0x000000012a073e05 -[PSPDFDocument destroyDocumentProviders] + 917 11 PSPDFKit 0x000000012a0533d7 -[PSPDFDocument dealloc] + 375 12 Foundation 0x000000010ef574e8 NSKVODeallocate + 158 13 libobjc.A.dylib 0x000000010f525a6e _ZN11objc_object17sidetable_releaseEb + 202 14 PSPDFKit 0x000000012ed587dd -[PSPDFRetainTracker release] + 1117 15 PSPDFKit 0x000000012a2a37f6 -[PSPDFRenderRequest .cxx_destruct] + 182 16 libobjc.A.dylib 0x000000010f50f920 _ZL27object_cxxDestructFromClassP11objc_objectP10objc_class + 127 17 libobjc.A.dylib 0x000000010f51b502 objc_destructInstance + 124 18 CoreFoundation 0x000000010ff98936 -[NSObject(NSObject) __dealloc_zombie] + 150 19 libobjc.A.dylib 0x000000010f525a6e _ZN11objc_object17sidetable_releaseEb + 202 20 PSPDFKit 0x000000012a02a208 -[PSPDFRenderTask .cxx_destruct] + 152 21 libobjc.A.dylib 0x000000010f50f920 _ZL27object_cxxDestructFromClassP11objc_objectP10objc_class + 127 22 libobjc.A.dylib 0x000000010f51b502 objc_destructInstance + 124 23 CoreFoundation 0x000000010ff98936 -[NSObject(NSObject) __dealloc_zombie] + 150 24 PSPDFKit 0x000000012a0204e9 -[PSPDFRenderTask dealloc] + 409 25 libobjc.A.dylib 0x000000010f525a6e _ZN11objc_object17sidetable_releaseEb + 202 26 CoreFoundation 0x000000010fe938bd -[__NSSetM dealloc] + 157 27 libobjc.A.dylib 0x000000010f525a6e _ZN11objc_object17sidetable_releaseEb + 202 28 PSPDFKit 0x000000012a1161fe -[PSPDFRenderJob .cxx_destruct] + 126 29 libobjc.A.dylib 0x000000010f50f920 _ZL27object_cxxDestructFromClassP11objc_objectP10objc_class + 127 30 libobjc.A.dylib 0x000000010f51b502 objc_destructInstance + 124 31 CoreFoundation 0x000000010ff98936 -[NSObject(NSObject) __dealloc_zombie] + 150 32 PSPDFKit 0x000000012a10ce39 -[PSPDFRenderJob dealloc] + 409 33 libobjc.A.dylib 0x000000010f525a6e _ZN11objc_object17sidetable_releaseEb + 202 34 PSPDFKit 0x000000012a115fcd __destroy_helper_block_.127 + 29 35 libsystem_blocks.dylib 0x000000011414d98a _Block_release + 111 36 PSPDFKit 0x000000012ec8334b __destroy_helper_block_.216 + 59 37 libsystem_blocks.dylib 0x000000011414d98a _Block_release + 111 38 libobjc.A.dylib 0x000000010f5261b2 _ZN12_GLOBAL__N_119AutoreleasePoolPage3popEPv + 860 39 libdispatch.dylib 0x0000000114066762 _dispatch_last_resort_autorelease_pool_pop + 27 40 libdispatch.dylib 0x0000000114070fc1 _dispatch_root_queue_drain + 1186 41 libdispatch.dylib 0x0000000114070ac1 _dispatch_worker_thread3 + 119 42 libsystem_pthread.dylib 0x00000001145881ca _pthread_wqthread + 1387 43 libsystem_pthread.dylib 0x0000000114587c4d start_wqthread + 13 ) Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  30. )AUTORELEASE 0x617000007780 (queue:com.apple.root.background-qos) -> ( 0 PSPDFKit 0x000000012ed5818b -[PSPDFRetainTracker autorelease]

    + 747 1 PSPDFKit 0x0000000129fbce4c _ZN5PSPDF2asI13PSPDFDocumentEEPT_P11objc_object + 652 2 PSPDFKit 0x0000000129fb83e3 _ZN5PSPDF11as_force_nnI13PSPDFDocumentEEPT_P8NSObject + 2563 3 PSPDFKit 0x0000000129fb8b02 -[PSPDFCacheDocumentHashManager willCloseDocument:] + 514 4 CoreFoundation 0x000000010feb2b8c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12 5 CoreFoundation 0x000000010feb2a65 _CFXRegistrationPost + 453 6 CoreFoundation 0x000000010feb27a1 ___CFXNotificationPost_block_invoke + 225 7 CoreFoundation 0x000000010fe74422 -[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1826 8 CoreFoundation 0x000000010fe735a1 _CFXNotificationPost + 609 9 Foundation 0x000000010eef2e57 -[NSNotificationCenter postNotificationName:object:userInfo:] + 66 10 PSPDFKit 0x000000012a073e05 -[PSPDFDocument destroyDocumentProviders] + 917 11 PSPDFKit 0x000000012a0533d7 -[PSPDFDocument dealloc] + 375 12 Foundation 0x000000010ef574e8 NSKVODeallocate + 158 13 libobjc.A.dylib 0x000000010f525a6e _ZN11objc_object17sidetable_releaseEb + 202 14 PSPDFKit 0x000000012ed587dd -[PSPDFRetainTracker release] + 1117 15 PSPDFKit 0x000000012a2a37f6 -[PSPDFRenderRequest .cxx_destruct] + 182 ) Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  31. )AUTORELEASE 0x617000007780 (queue:com.apple.root.background-qos) -> ( 0 PSPDFKit 0x000000012ed5818b -[PSPDFRetainTracker autorelease]

    + 747 1 PSPDFKit 0x0000000129fbce4c _ZN5PSPDF2asI13PSPDFDocumentEEPT_P11objc_object + 652 2 PSPDFKit 0x0000000129fb83e3 _ZN5PSPDF11as_force_nnI13PSPDFDocumentEEPT_P8NSObject + 2563 3 PSPDFKit 0x0000000129fb8b02 -[PSPDFCacheDocumentHashManager willCloseDocument:] + 514 4 CoreFoundation 0x000000010feb2b8c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12 5 CoreFoundation 0x000000010feb2a65 _CFXRegistrationPost + 453 6 CoreFoundation 0x000000010feb27a1 ___CFXNotificationPost_block_invoke + 225 7 CoreFoundation 0x000000010fe74422 -[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1826 8 CoreFoundation 0x000000010fe735a1 _CFXNotificationPost + 609 9 Foundation 0x000000010eef2e57 -[NSNotificationCenter postNotificationName:object:userInfo:] + 66 10 PSPDFKit 0x000000012a073e05 -[PSPDFDocument destroyDocumentProviders] + 917 11 PSPDFKit 0x000000012a0533d7 -[PSPDFDocument dealloc] + 375 12 Foundation 0x000000010ef574e8 NSKVODeallocate + 158 13 libobjc.A.dylib 0x000000010f525a6e _ZN11objc_object17sidetable_releaseEb + 202 14 PSPDFKit 0x000000012ed587dd -[PSPDFRetainTracker release] + 1117 15 PSPDFKit 0x000000012a2a37f6 -[PSPDFRenderRequest .cxx_destruct] + 182 ) Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  32. - (void)willCloseDocument:(NSNotification *)aNotification { let document = PSPDF::as_force_nn<PSPDFDocument>(aNotification.object); if (document.hasUnsavedChanges

    || document.hasDirtyAnnotations) { return; } [self updateHashesForDocument:document]; } Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  33. - (void)willCloseDocument:(NSNotification *)aNotification { let document = PSPDF::as_force_nn<PSPDFDocument>(aNotification.object); if (document.hasUnsavedChanges

    || document.hasDirtyAnnotations) { return; } [self updateHashesForDocument:document]; } Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  34. /// as? Casts nullable object to type T. Return nil

    if wrong type. template <class T> inline T *_Nullable as(id _Nullable o) noexcept { if ([o isKindOfClass:[T class]]) { return (T * _Nullable)o; } return nil; } Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  35. /// as? Casts nullable object to type T. Return nil

    if wrong type. template <class T> inline T *_Nullable as(id _Nullable o) noexcept { if ([o isKindOfClass:[T class]]) { return (T * _Nullable)o; } return nil; } Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  36. /// as? Casts nullable object to type T. Return nil

    if wrong type. template <class T> inline __attribute__((always_inline)) T *_Nullable as(id _Nullable o) noexcept { if ([o isKindOfClass:[T class]]) { return (T * _Nullable)o; } return nil; } Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  37. Recap โ†’ Best debugging is no debugging โ†’ brew install

    chisel โ†’ Enable Xcode Hard Mode โ†’ Use the Force Sanitizers โ†’ Remember the Memory Graph Debugger โ†’ When debugging, anything goes Peter Steinberger โ€” @steipete โ€” PSPDFKit.com
  38. Thanks for listening! Slides: @steipete on Twitter Picking Apart the

    Crashing iOS String: https://manishearth.github.io/blog/2018/02/15/picking-apart-the-crashing-ios-string/ Testing with Address Sanitizer: https://pspdfkit.com/blog/2016/test-with-asan/ Chisel Cheat Cheet: https://kapeli.com/cheat_sheets/LLDB_Chisel_Commands.docset/Contents/Resources/Documents/index iOS Device List with maximum supported version: https://everyi.com/by-capability/maximum-supported-ios-version-for-ipod-iphone-ipad.html Undefined Behavior Sanitizer: https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html Swift and Warnings: https://twitter.com/jckarter/status/972894889221414912 Self-Written Main Thread Guard: https://gist.github.com/steipete/5664345 Scripted Breakpoints: https://pspdfkit.com/blog/2016/scripted-breakpoints/ User Breakpoints: https://pspdfkit.com/blog/2017/user-breakpoints-in-xcode/ Swift Compiler Bug Hunt: https://topologyeyewear.github.io/engineering-blog/2018/03/07/heap_corruption/ View Layout Feedback Loop Debugger: https://developer.apple.com/videos/play/wwdc2016/236 Visual Debugging with Xcode: https://developer.apple.com/videos/play/wwdc2016/410 Make UI Tests Fast: https://pspdfkit.com/blog/2016/running-ui-tests-with-ludicrous-speed/ Smart Debugging โ€” TEKI CON Atlanta, March 2018 โ€” Peter Steinberger โ€” @steipete โ€” PSPDFKit.com