Slide 1

Slide 1 text

Smart Debugging Peter Steinberger — @steipete TEKI CON Atlanta, March 2018

Slide 2

Slide 2 text

U+0C1C U+0C4D U+0C1E U+200C U+0C3Ex Peter Steinberger — @steipete — PSPDFKit.com

Slide 3

Slide 3 text

Peter Steinberger — @steipete — PSPDFKit.com

Slide 4

Slide 4 text

Peter Steinberger — @steipete — PSPDFKit.com

Slide 5

Slide 5 text

Peter Steinberger — @steipete — PSPDFKit.com

Slide 6

Slide 6 text

Peter Steinberger — @steipete — PSPDFKit.com

Slide 7

Slide 7 text

PSPDFKit iOS, macOS, Android, Windows, Server, WebAssembly Peter Steinberger — @steipete — PSPDFKit.com

Slide 8

Slide 8 text

Categories of Bugs → Business Logic → Performance → API Misuse → View → Memory → Locking/Threading/Races Peter Steinberger — @steipete — PSPDFKit.com

Slide 9

Slide 9 text

Categories of Bugs → Business Logic Tests → Performance → API Misuse → View → Memory → Locking/Threading/Races Peter Steinberger — @steipete — PSPDFKit.com

Slide 10

Slide 10 text

Categories of Bugs → Business Logic Tests → Performance ➡ Instruments + Measure → API Misuse → View → Memory → Locking/Threading/Races Peter Steinberger — @steipete — PSPDFKit.com

Slide 11

Slide 11 text

Categories of Bugs → Business Logic Tests → Performance ➡ Instruments + Measure → API Misuse ➡ Documentation + Asserts → View → Memory → Locking/Threading/Races Peter Steinberger — @steipete — PSPDFKit.com

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

Debug for any ObjC Object @interface NSObject (Private) -(id)_ivarDescription; -(id)_shortMethodDescription; -(id)_methodDescription; @end Peter Steinberger — @steipete — PSPDFKit.com

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

View Debugging Helper Category @interface UIView (Debug) - (id)recursiveDescription; @end po self.recursiveDescription() as NSString Peter Steinberger — @steipete — PSPDFKit.com

Slide 16

Slide 16 text

.lldbinit command alias alt expr -l objc++ -O --[[UIWindow keyWindow] _autolayoutTrace] Peter Steinberger — @steipete — PSPDFKit.com

Slide 17

Slide 17 text

github.com/facebook/chisel Command Explanation pa11y 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 Print the actions/targets of a control Peter Steinberger — @steipete — PSPDFKit.com

Slide 18

Slide 18 text

findinstances 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

Slide 19

Slide 19 text

findinstances 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

Slide 20

Slide 20 text

findinstances 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

Slide 21

Slide 21 text

findinstances 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

Slide 22

Slide 22 text

Memory Graph Debugger Peter Steinberger — @steipete — PSPDFKit.com

Slide 23

Slide 23 text

Memory Graph Debugger Peter Steinberger — @steipete — PSPDFKit.com

Slide 24

Slide 24 text

Peter Steinberger — @steipete — PSPDFKit.com

Slide 25

Slide 25 text

Peter Steinberger — @steipete — PSPDFKit.com

Slide 26

Slide 26 text

Peter Steinberger — @steipete — PSPDFKit.com

Slide 27

Slide 27 text

@interface PSPDFRenderedImage : UIImage @end @implementation PSPDFRenderedImage @end object_setClass(image, PSPDFRenderedImage.class); Peter Steinberger — @steipete — PSPDFKit.com

Slide 28

Slide 28 text

Peter Steinberger — @steipete — PSPDFKit.com

Slide 29

Slide 29 text

PDFViewer.io Peter Steinberger — @steipete — PSPDFKit.com

Slide 30

Slide 30 text

Clang Analyzer Peter Steinberger — @steipete — PSPDFKit.com

Slide 31

Slide 31 text

Peter Steinberger — @steipete — PSPDFKit.com

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

#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

Slide 35

Slide 35 text

/** 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

Slide 36

Slide 36 text

-Weverything Hard Mode in Xcode Peter Steinberger — @steipete — PSPDFKit.com

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

#pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" ... #pragma clang diagnostic pop Peter Steinberger — @steipete — PSPDFKit.com

Slide 40

Slide 40 text

Clang Sanitizers → Address Sanitizer → Undefined Behaviour Sanitizer → Main Thread Checker → Thread Sanitizer Peter Steinberger — @steipete — PSPDFKit.com

Slide 41

Slide 41 text

Peter Steinberger — @steipete — PSPDFKit.com

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

// 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

Slide 44

Slide 44 text

Hunting an Over-Release *** -[PSPDFDocument release]: message sent to deallocated instance 0x617000007780 Peter Steinberger — @steipete — PSPDFKit.com

Slide 45

Slide 45 text

// 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

Slide 46

Slide 46 text

Peter Steinberger — @steipete — PSPDFKit.com

Slide 47

Slide 47 text

ARC objc_autorelease() _swift_objc_autoreleasePoolPop() swift_retain() Peter Steinberger — @steipete — PSPDFKit.com

Slide 48

Slide 48 text

ARC, the Enemy Peter Steinberger — @steipete — PSPDFKit.com

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

+ (void)initialize { class_setSuperclass(PSPDFDocument.class, (Class)NSClassFromString(@"PSPDFRetainTracker")); } Peter Steinberger — @steipete — PSPDFKit.com

Slide 51

Slide 51 text

/** * 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

Slide 52

Slide 52 text

)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

Slide 53

Slide 53 text

)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

Slide 54

Slide 54 text

)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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

Peter Steinberger — @steipete — PSPDFKit.com

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

/// as? Casts nullable object to type T. Return nil if wrong type. template 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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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