•finding bugs using xcode runtime tools...•finding bugs using xcode runtime tools • session...

192
#WWDC17 © 2017 Apple Inc. All rights reserved. Redistribution or public display not permitted without written permission from Apple. Kuba Mracek, Program Analysis Engineer Vedant Kumar, Compiler Engineer Finding Bugs Using Xcode Runtime Tools Session 406 Developer Tools

Upload: others

Post on 03-Jun-2020

48 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

#WWDC17

© 2017 Apple Inc. All rights reserved. Redistribution or public display not permitted without written permission from Apple.

Kuba Mracek, Program Analysis Engineer Vedant Kumar, Compiler Engineer

•Finding BugsUsing Xcode Runtime Tools • Session 406

Developer Tools

Page 2: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Improvements in Runtime Checking

Page 3: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Improvements in Runtime Checking

Page 4: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Improvements in Runtime Checking

Page 5: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Improvements in Runtime Checking

Page 6: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Improvements in Runtime Checking

Page 7: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Improvements in Runtime Checking

Runtime Issues

Page 8: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 9: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 10: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 11: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 12: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

4

Page 13: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

4

Page 14: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

4

Page 15: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 16: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 17: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 18: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Address Sanitizer

Thread Sanitizer

Undefined Behavior Sanitizer

Main Thread Checker

Page 19: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

•Main Thread Checker •Address Sanitizer •Thread Sanitizer •Undefined Behavior Sanitizer •Using Runtime Tools Effectively

Page 20: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

•Main Thread Checker •Address Sanitizer •Thread Sanitizer •Undefined Behavior Sanitizer •Using Runtime Tools Effectively

•New

Page 21: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

•Main Thread Checker •Address Sanitizer •Thread Sanitizer •Undefined Behavior Sanitizer •Using Runtime Tools Effectively

•New

•New

Page 22: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

•Main Thread Checker •Detects misuses of common APIs

NEW

Page 23: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

UI Updates and Threads

Some APIs must only be used from the main thread

Page 24: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

UI Updates and Threads

Main Thread

Background Thread

Page 25: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

UI Updates and Threads

Main Thread

AppKit.framework UIKit.framework

Background Thread

Page 26: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

UI Updates and Threads

Main ThreadAppKit.framework UIKit.framework

Background Thread

Page 27: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

UI Updates and Threads

Main ThreadAppKit.framework UIKit.framework

File downloads Image processing

Background Thread

Page 28: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

UI Updates and Threads

Main ThreadAppKit.framework UIKit.framework

File downloads Image processingBackground Thread

Page 29: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

UI Updates and Threads

Main ThreadAppKit.framework UIKit.framework

File downloads Image processing

UI update

Background Thread

Page 30: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

UI Updates and Threads

Main ThreadAppKit.framework UIKit.framework

File downloads Image processing UI updateBackground Thread !

Page 31: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

UI Updates and Threads

Main ThreadAppKit.framework UIKit.framework

File downloads Image processing UI updateBackground Thread Missed UI updates Visual defects

Data corruptions Crashes

Page 32: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

UI Updates and Threads

Main ThreadAppKit.framework UIKit.framework

File downloads Image processing

UI update ✓Background Thread

Page 33: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

•Demo •Main Thread Checker

Page 34: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 35: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 36: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 37: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Common Places for Mistakes

Networking callbacks

Creating and destroying NSView and UIView objects

Designing asynchronous APIs

Page 38: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Designing Asynchronous APIs

Let API user specify callback queue

Page 39: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Designing Asynchronous APIs

Let API user specify callback queue

DeepThought.asyncComputeAnswer(to: theQuestion) { reply in … }

Page 40: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Designing Asynchronous APIs

Let API user specify callback queue

DeepThought.asyncComputeAnswer(to: theQuestion, completionQueue: queue) { reply in … }

Page 41: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Main Thread Checker

Detects violations of API threading rules

AppKit, UIKit and WebKit APIs

Swift and C languages

No recompilation

Enabled by default in the Xcode debugger

NEW

Page 42: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

•Address Sanitizer •Detects memory issues

Page 43: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Finding Memory Issues

Security critical bugs • Use-after-free and buffer overflows

Diagnoses hard-to-reproduce crashes

Advanced Debugging and the Address Sanitizer WWDC 2015

Page 44: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 45: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 46: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 47: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 48: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 49: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 50: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 51: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 52: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 53: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 54: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Address Sanitizer in Xcode 9

Detects use-after-scope

Detects use-after-return (opt-in)

Compatible with Malloc Scribble

NEW

Page 55: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use of Stack Memory Out of Scope

int *integer_pointer = NULL; if (is_some_condition_true()) { int value = calculate_value(); integer_pointer = &value; } *integer_pointer = 42;

Page 56: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use of Stack Memory Out of Scope

int *integer_pointer = NULL; if (is_some_condition_true()) { int value = calculate_value(); integer_pointer = &value; } *integer_pointer = 42;

Page 57: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use of Stack Memory Out of Scope

int *integer_pointer = NULL; if (is_some_condition_true()) { int value = calculate_value(); integer_pointer = &value; } *integer_pointer = 42;

Page 58: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use of Stack Memory Out of Scope

int *integer_pointer = NULL; if (is_some_condition_true()) { int value = calculate_value(); integer_pointer = &value; } *integer_pointer = 42;

Page 59: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Use of out of scope stack memory

// Use of Stack Memory Out of Scope

int *integer_pointer = NULL; if (is_some_condition_true()) { int value = calculate_value(); integer_pointer = &value; } *integer_pointer = 42;

Page 60: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use of Stack Memory after Return

int *returns_address_of_stack() { int a = 42; return &a; }

int *integer_pointer = returns_address_of_stack(); *integer_pointer = 43;

Page 61: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use of Stack Memory after Return

int *returns_address_of_stack() { int a = 42; return &a; }

int *integer_pointer = returns_address_of_stack(); *integer_pointer = 43;

Page 62: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use of Stack Memory after Return

int *returns_address_of_stack() { int a = 42; return &a; }

int *integer_pointer = returns_address_of_stack(); *integer_pointer = 43;

Page 63: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use of Stack Memory after Return

int *returns_address_of_stack() { int a = 42; return &a; }

int *integer_pointer = returns_address_of_stack(); *integer_pointer = 43;

Page 64: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Use of stack memory after return

// Use of Stack Memory after Return

int *returns_address_of_stack() { int a = 42; return &a; }

int *integer_pointer = returns_address_of_stack(); *integer_pointer = 43;

Page 65: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Address Sanitizer and Swift

Swift is a much safer language

Mixed projects

Unsafe pointer types are not memory safe

Page 66: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use-after-free Bug Using UnsafePointer

let string = "Hello, World!" var firstBytePointer: UnsafePointer<CChar> … string.withCString { pointerToCString in firstBytePointer = pointerToCString } … let firstByte = firstBytePointer.pointee print(firstByte)

Page 67: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use-after-free Bug Using UnsafePointer

let string = "Hello, World!" var firstBytePointer: UnsafePointer<CChar> … string.withCString { pointerToCString in firstBytePointer = pointerToCString } … let firstByte = firstBytePointer.pointee print(firstByte)

Page 68: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use-after-free Bug Using UnsafePointer

let string = "Hello, World!" var firstBytePointer: UnsafePointer<CChar> … string.withCString { pointerToCString in firstBytePointer = pointerToCString } … let firstByte = firstBytePointer.pointee print(firstByte)

Page 69: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use-after-free Bug Using UnsafePointer

let string = "Hello, World!" var firstBytePointer: UnsafePointer<CChar> … string.withCString { pointerToCString in firstBytePointer = pointerToCString } … let firstByte = firstBytePointer.pointee print(firstByte)

Page 70: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use-after-free Bug Using UnsafePointer

let string = "Hello, World!" var firstBytePointer: UnsafePointer<CChar> … string.withCString { pointerToCString in firstBytePointer = pointerToCString } … let firstByte = firstBytePointer.pointee print(firstByte)

Page 71: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use-after-free Bug Using UnsafePointer

let string = "Hello, World!" var firstBytePointer: UnsafePointer<CChar> … string.withCString { pointerToCString in firstBytePointer = pointerToCString } … let firstByte = firstBytePointer.pointee print(firstByte)

Page 72: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Use of deallocated memory

// Use-after-free Bug Using UnsafePointer

let string = "Hello, World!" var firstBytePointer: UnsafePointer<CChar> … string.withCString { pointerToCString in firstBytePointer = pointerToCString } … let firstByte = firstBytePointer.pointee print(firstByte)

Page 73: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use UnsafePointer Only Inside the Closure

let string = "Hello, World!" var firstBytePointer: UnsafePointer<CChar> … string.withCString { pointerToCString in firstBytePointer = pointerToCString } … let firstByte = firstBytePointer.pointee print(firstByte)

Page 74: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use UnsafePointer Only Inside the Closure

let string = "Hello, World!"

string.withCString { pointerToCString in var firstBytePointer: UnsafePointer<CChar> firstBytePointer = pointerToCString … let firstByte = firstBytePointer.pointee print(firstByte) }

Page 75: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use UnsafePointer Only Inside the Closure

let string = "Hello, World!"

string.withCString { pointerToCString in var firstBytePointer: UnsafePointer<CChar> firstBytePointer = pointerToCString … let firstByte = firstBytePointer.pointee print(firstByte) }

Page 76: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use UnsafePointer Only Inside the Closure

let string = "Hello, World!"

string.withCString { pointerToCString in var firstBytePointer: UnsafePointer<CChar> firstBytePointer = pointerToCString … let firstByte = firstBytePointer.pointee print(firstByte) }

Page 77: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use UnsafePointer Only Inside the Closure

let string = "Hello, World!"

string.withCString { pointerToCString in … let firstByte = pointerToCString.pointee print(firstByte) }

Page 78: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Better Debugging Experience

Makes debugging easier

Allocation and deallocation backtraces

Shows valid and invalid bytes of memory

Page 79: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 80: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 81: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 82: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 83: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 84: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 85: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 86: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 87: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 88: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 89: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 90: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

memory history <expression>

Page 91: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

memory history 0x602000007cd0

Page 92: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

memory history 0x602000007cd0thread ..., name = 'Memory deallocated by Thread 1'frame #0: 0x1000fba26 wrap_free + 198frame #1: 0x100001c04 deallocate(p=<unavailable>) at main.m:8frame #2: 0x100001ce8 perform_heap_operations at main.m:15frame #3: 0x100001d1a main(argc=<unavailable>, argv=<unavailable>) at main.m:28

thread ..., name = 'Memory allocated by Thread 1'frame #0: 0x1000fb85c wrap_malloc + 188frame #1: 0x100001bdf allocate at main.m:4frame #2: 0x100001c1c perform_heap_operations at main.m:12frame #3: 0x100001d1a main(argc=<unavailable>, argv=<unavailable>) at main.m:28

Page 93: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

When to Use Address Sanitizer

C languages and Swift

Memory corruptions and crashes

General debugging

Page 94: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

•Thread Sanitizer •Detects multithreading problems

Page 95: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

What is Thread Sanitizer

Multithreading issues

Finds races even if they did not manifest

64-bit macOS, 64-bit simulators

Thread Sanitizer and Static Analysis WWDC 2016

Page 96: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Data Races

Unsynchronized accesses to shared mutable variables

Lead to data races

Memory corruptions and crashes

All of these problems apply to Swift!

Page 97: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Swift Data Race Example

class EventLog { private var lastEventSource: LogSource?

func log(source: LogSource, message: String) { print(message) lastEventSource = source } }

Page 98: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Swift Data Race Example

class EventLog { private var lastEventSource: LogSource?

func log(source: LogSource, message: String) { print(message) lastEventSource = source } }

Page 99: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Swift Data Race Example

class EventLog { private var lastEventSource: LogSource?

func log(source: LogSource, message: String) { print(message) lastEventSource = source } }

Page 100: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Swift Data Race Example

class EventLog { private var lastEventSource: LogSource?

func log(source: LogSource, message: String) { print(message) lastEventSource = source } }

Page 101: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Swift Data Race Example

class EventLog { private var lastEventSource: LogSource?

func log(source: LogSource, message: String) { print(message) lastEventSource = source } }

Page 102: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Thread 1 eventLog.log(source: networkingSubsystem, message: "Download finished")

// Thread 2 eventLog.log(source: databaseSubsystem, message: "Query complete")

// Swift Data Race Example

class EventLog { private var lastEventSource: LogSource?

func log(source: LogSource, message: String) { print(message) lastEventSource = source } }

Page 103: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Thread 1 eventLog.log(source: networkingSubsystem, message: "Download finished")

// Thread 2 eventLog.log(source: databaseSubsystem, message: "Query complete")

// Swift Data Race Example

class EventLog { private var lastEventSource: LogSource?

func log(source: LogSource, message: String) { print(message) lastEventSource = source } }

Page 104: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Thread 1 eventLog.log(source: networkingSubsystem, message: "Download finished")

// Thread 2 eventLog.log(source: databaseSubsystem, message: "Query complete")

Thread 2: Data race in EventLog.log(source:message:)

// Swift Data Race Example

class EventLog { private var lastEventSource: LogSource?

func log(source: LogSource, message: String) { print(message) lastEventSource = source } }

Page 105: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use DispatchQueue to Synchronize Access

class EventLog { private var lastEventSource: LogSource?

func log(source: LogSource, message: String) { print(message) lastEventSource = source } }

Page 106: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use DispatchQueue to Synchronize Access

class EventLog { private var lastEventSource: LogSource? private var queue = DispatchQueue(label: "com.example.EventLog.queue")

func log(source: LogSource, message: String) { print(message) lastEventSource = source } }

Page 107: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use DispatchQueue to Synchronize Access

class EventLog { private var lastEventSource: LogSource? private var queue = DispatchQueue(label: "com.example.EventLog.queue")

func log(source: LogSource, message: String) { print(message) lastEventSource = source } }

Page 108: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use DispatchQueue to Synchronize Access

class EventLog { private var lastEventSource: LogSource? private var queue = DispatchQueue(label: "com.example.EventLog.queue")

func log(source: LogSource, message: String) { queue.async { print(message) lastEventSource = source } } }

Page 109: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use DispatchQueue to Synchronize Access

class EventLog { private var lastEventSource: LogSource? private var queue = DispatchQueue(label: "com.example.EventLog.queue")

func log(source: LogSource, message: String) { queue.async { print(message) lastEventSource = source } } }

Page 110: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use DispatchQueue to Synchronize Access

class EventLog { private var lastEventSource: LogSource? private var queue = DispatchQueue(label: "com.example.EventLog.queue")

func log(source: LogSource, message: String) { queue.async { print(message) lastEventSource = source } } }

Page 111: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Dispatch Queues

Grand Central Dispatch should be your first choice of synchronization

Lightweight, convenient, simple

Associate your data with serial dispatch queues

Concurrent Programming With GCD in Swift 3 WWDC 2016

Page 112: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

New in Thread Sanitizer in Xcode 9

Races on collections

Swift access races

NEW

Page 113: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Previously, only reported races on raw memory accesses

Synchronization required for larger data structures

Races on Collections

Page 114: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Previously, only reported races on raw memory accesses

Synchronization required for larger data structures

Races on Collections

NSMutableDictionary *d = [NSMutableDictionary new]; // Thread 1 BOOL found = [d objectForKey:@"answer"] != nil; // Thread 2 [d setObject:@42 forKey:@"answer"];

Page 115: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Previously, only reported races on raw memory accesses

Synchronization required for larger data structures

Races on Collections

Thread 2: Race on NSMutableDictionary

Thread 1: Previous access on NSMutableDictionary

NSMutableDictionary *d = [NSMutableDictionary new]; // Thread 1 BOOL found = [d objectForKey:@"answer"] != nil; // Thread 2 [d setObject:@42 forKey:@"answer"];

Page 116: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Races on collections in Objective-C and Swift

NSMutableArray, NSMutableDictionary

Swift Array and Dictionary

Races on CollectionsNEW

Page 117: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

•Demo •Thread Sanitizer and race on NSMutableArray

Page 118: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Race on Swift Array

var usernames: [String] = ["alice", "bob"]

Page 119: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Race on Swift Array

var usernames: [String] = ["alice", "bob"]

// Thread 1 found = usernames.contains("alice") if found { … }

// Thread 2 usernames.append("carol")

Page 120: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Thread 2: Swift access race

Thread 1: Previous access

// Race on Swift Array

var usernames: [String] = ["alice", "bob"]

// Thread 1 found = usernames.contains("alice") if found { … }

// Thread 2 usernames.append("carol")

Page 121: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use DispatchQueue to Synchronize Accesses

var usernames: [String] = ["alice", "bob"]

// Thread 1 found = usernames.contains("alice") if found { … }

// Thread 2 usernames.append("carol")

Page 122: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use DispatchQueue to Synchronize Accesses

var usernames: [String] = ["alice", "bob"] var queue = DispatchQueue(label: "com.example.usernames.queue")

// Thread 1 found = usernames.contains("alice") if found { … }

// Thread 2 usernames.append("carol")

Page 123: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use DispatchQueue to Synchronize Accesses

var usernames: [String] = ["alice", "bob"] var queue = DispatchQueue(label: "com.example.usernames.queue")

// Thread 1 found = usernames.contains("alice") if found { … }

// Thread 2 usernames.append("carol")

Page 124: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use DispatchQueue to Synchronize Accesses

var usernames: [String] = ["alice", "bob"] var queue = DispatchQueue(label: "com.example.usernames.queue")

// Thread 1 found = usernames.contains("alice") if found { … }

// Thread 2 usernames.append("carol")

Page 125: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Thread 2 queue.async { usernames.append("carol") }

// Use DispatchQueue to Synchronize Accesses

var usernames: [String] = ["alice", "bob"] var queue = DispatchQueue(label: "com.example.usernames.queue")

// Thread 1 queue.sync { found = usernames.contains("alice") } if found { … }

Page 126: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Thread 2 queue.async { usernames.append("carol") }

// Use DispatchQueue to Synchronize Accesses

var usernames: [String] = ["alice", "bob"] var queue = DispatchQueue(label: "com.example.usernames.queue")

// Thread 1 queue.sync { found = usernames.contains("alice") } if found { … }

Page 127: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Swift Access Races

Applies to all structs

Mutating methods require exclusive access to the whole struct

Methods on classes require exclusive access to stored properties they change

NEW

What's New in Swift Tuesday 1:50PM

Page 128: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Swift Access Race with Mutating Methods

struct BluePoliceBoxLocation { private var x, y, z: Int private var time: Int

}

Page 129: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Swift Access Race with Mutating Methods

struct BluePoliceBoxLocation { private var x, y, z: Int private var time: Int

}

mutating func teleport(toPlanet: String) { … } mutating func fly(toCity: String) { … } mutating func travelToEndOfTime() { … }

Page 130: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Swift Access Race with Mutating Methods

struct BluePoliceBoxLocation { private var x, y, z: Int private var time: Int

}

mutating func teleport(toPlanet: String) { … } mutating func fly(toCity: String) { … } mutating func travelToEndOfTime() { … }

Page 131: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Swift Access Race with Mutating Methods

struct BluePoliceBoxLocation { private var x, y, z: Int private var time: Int

}

mutating func teleport(toPlanet: String) { … } mutating func fly(toCity: String) { … } mutating func travelToEndOfTime() { … }

// Thread 1 location.teleport(toPlanet: "Mars")

// Thread 2 location.travelToEndOfTime()

Page 132: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Swift Access Race with Mutating Methods

struct BluePoliceBoxLocation { private var x, y, z: Int private var time: Int

}

mutating func teleport(toPlanet: String) { … } mutating func fly(toCity: String) { … } mutating func travelToEndOfTime() { … }

Thread 2: Swift access race

Thread 1: Previous access

// Thread 1 location.teleport(toPlanet: "Mars")

// Thread 2 location.travelToEndOfTime()

Page 133: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Swift Access Race with Mutating Methods

struct BluePoliceBoxLocation { private var x, y, z: Int private var time: Int

}

mutating func teleport(toPlanet: String) { … } mutating func fly(toCity: String) { … } mutating func travelToEndOfTime() { … }

Thread 2: Swift access race

Thread 1: Previous access

// Thread 1 location.teleport(toPlanet: "Mars")

// Thread 2 location.travelToEndOfTime()

changes x, y, z

changes time

Page 134: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Swift Access Race with Mutating Methods

struct BluePoliceBoxLocation { private var x, y, z: Int private var time: Int

}

mutating func teleport(toPlanet: String) { … } mutating func fly(toCity: String) { … } mutating func travelToEndOfTime() { … }

Thread 2: Swift access race

Thread 1: Previous access

// Thread 1 location.teleport(toPlanet: "Mars")

// Thread 2 location.travelToEndOfTime()

Page 135: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Incorrect Synchronization Inside a Struct

struct BluePoliceBoxLocation { private var x, y, z: Int private var time: Int

mutating func teleport(toPlanet: String) { … } mutating func fly(toCity: String) { … } mutating func travelToEndOfTime() { … } }

Page 136: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Incorrect Synchronization Inside a Struct

struct BluePoliceBoxLocation { private var x, y, z: Int private var time: Int private var queue: DispatchQueue = …

mutating func teleport(toPlanet: String) { queue.sync { … } } mutating func fly(toCity: String) { queue.sync { … } } mutating func travelToEndOfTime() { queue.sync { … } } }

Page 137: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Incorrect Synchronization Inside a Struct

struct BluePoliceBoxLocation { private var x, y, z: Int private var time: Int private var queue: DispatchQueue = …

mutating func teleport(toPlanet: String) { queue.sync { … } } mutating func fly(toCity: String) { queue.sync { … } } mutating func travelToEndOfTime() { queue.sync { … } } }

Page 138: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Incorrect Synchronization Inside a Struct

struct BluePoliceBoxLocation { private var x, y, z: Int private var time: Int private var queue: DispatchQueue = …

mutating func teleport(toPlanet: String) { queue.sync { … } } mutating func fly(toCity: String) { queue.sync { … } } mutating func travelToEndOfTime() { queue.sync { … } } }

Page 139: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Synchronize Calls to Mutating Methods

struct BluePoliceBoxLocation { … }

Page 140: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Synchronize Calls to Mutating Methods

struct BluePoliceBoxLocation { … } class BluePoliceBox { private var location: BluePoliceBoxLocation private var queue: DispatchQueue = …

}

Page 141: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Synchronize Calls to Mutating Methods

struct BluePoliceBoxLocation { … } class BluePoliceBox { private var location: BluePoliceBoxLocation private var queue: DispatchQueue = …

}

func goOnRescueMission() { queue.sync { location.teleport(toPlanet: "Mars") … } } func goToWrongPlaceAgain() { queue.sync { … } }

Page 142: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Find and Fix Your Races

Use GCD to synchronize access to data

Associate your shared data with a serial queue

Thread Sanitizer is invaluable for finding races

Page 143: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Vedant Kumar, Compiler Engineer

•Undefined Behavior Sanitizer

NEW

Page 144: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

What is Undefined Behavior Sanitizer?

Runtime bug finder

Checks unsafe constructs in the C language family

Compatible with other runtime tools

Understanding Undefined Behavior Executive Ballroom Thursday 9:00AM

Page 145: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 146: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Alignment Violation

Nonnull Return Value Violation

Integer Overflow

C++ Dynamic Type Violation Invalid Float Cast

Invalid Shift Exponent

Invalid Boolean Invalid EnumInvalid Variable-Length Array Integer Division by Zero

Invalid Shift BaseInvalid Integer Cast

Out-of-Bounds Array Access

Invalid Object SizeMissing Return Value

Reached Unreachable Code

Nonnull Parameter ViolationNonnull Assignment Violation

Null Dereference

Page 147: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Alignment Violation

Nonnull Return Value Violation

Integer Overflow

Page 148: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Arithmetic result too big

Unsafe in indexing expressions

(INT_MAX + 1) ≯ INT_MAX

Opt-in check for unsigned overflow

Integer Overflow

Page 149: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

•Demo •Undefined Behavior Sanitizer and integer overflow

Page 150: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Alignment Violation

Unaligned load or store

Causes crashes in Release builds

Common in (de)serialization code

Page 151: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Serializing Packets for a Custom Network Protocol

struct Packet { int magic; int payloadLength; char payload[]; };

Page 152: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Serializing Packets for a Custom Network Protocol

struct Packet { int magic; int payloadLength; char payload[]; };

// Sender

Page 153: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Serializing Packets for a Custom Network Protocol

struct Packet { int magic; int payloadLength; char payload[]; };

// Sender

77 77 64 63

Page 154: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Serializing Packets for a Custom Network Protocol

struct Packet { int magic; int payloadLength; char payload[]; };

// Sender

77 77 64 63 9

Page 155: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Serializing Packets for a Custom Network Protocol

struct Packet { int magic; int payloadLength; char payload[]; };

// Sender

77 77 64 63 9 H e y

K u b a !

Page 156: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Serializing Packets for a Custom Network Protocol

struct Packet { int magic; int payloadLength; char payload[]; };

// Receiver // Read from stream Packet *P = (Packet *)byteStream; if (P->magic != …) …

// Sender

77 77 64 63 9 H e y

K u b a !

Page 157: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Serializing Packets for a Custom Network Protocol

struct Packet { int magic; int payloadLength; char payload[]; };

// Receiver // Read from stream Packet *P = (Packet *)byteStream; if (P->magic != …) …

// Sender

77 77 64 63 9 H e y

K u b a !

Page 158: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Serializing Packets for a Custom Network Protocol

struct Packet { int magic; int payloadLength; char payload[]; };

// Sender

77 77 64 63 9 H e y

K u b a !

Page 159: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Serializing Packets for a Custom Network Protocol

struct Packet { int magic; int payloadLength; char payload[]; };

// Sender

77 77 64 63 9 H e y

K u b a ! 77 77 64 63

Page 160: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Serializing Packets for a Custom Network Protocol

struct Packet { int magic; int payloadLength; char payload[]; };

// Sender

77 77 64 63 9 H e y

K u b a ! 77 77 64 63

15

Page 161: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Serializing Packets for a Custom Network Protocol

struct Packet { int magic; int payloadLength; char payload[]; };

// Sender

77 77 64 63 9 H e y

K u b a ! 77 77 64 63

15 H o w ‘ s i t g o

i n g ?

Page 162: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Serializing Packets for a Custom Network Protocol

struct Packet { int magic; int payloadLength; char payload[]; };

// Sender

// Receiver // Read from stream Packet *P = (Packet *)(byteStream + 17); if (P->magic != …) …

77 77 64 63 9 H e y

K u b a ! 77 77 64 63

15 H o w ‘ s i t g o

i n g ?

Page 163: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Serializing Packets for a Custom Network Protocol

struct Packet { int magic; int payloadLength; char payload[]; };

// Sender

// Receiver // Read from stream Packet *P = (Packet *)(byteStream + 17); if (P->magic != …) …

77 77 64 63 9 H e y

K u b a ! 77 77 64

‘ s i

63

t g o15 H o w

i n g ?

Page 164: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Serializing Packets for a Custom Network Protocol

struct Packet { int magic; int payloadLength; char payload[]; };

Load of misaligned address

// Sender

77 77 64 63 9 H e y

K u b a !

// Receiver // Read from stream Packet *P = (Packet *)(byteStream + 17); if (P->magic != …) …

77 77 64 63

Page 165: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Serializing Packets for a Custom Network Protocol

struct Packet { int magic; int payloadLength; char payload[]; };

Load of misaligned address

// Sender

77 77 64 63 9 H e y

K u b a !

// Receiver // Read from stream Packet *P = (Packet *)(byteStream + 17); if (P->magic != …) …

77 77 64 63

Page 166: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use Structure Packing to Decrease Expected Alignment

struct Packet { int magic; int payloadLength; char payload[]; } __attribute__((packed));

// Read from stream Packet *P = (Packet *)byteStream; if (P->magic != …) …

Page 167: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Member alignment changes to 1

// Use Structure Packing to Decrease Expected Alignment

struct Packet { int magic; int payloadLength; char payload[]; } __attribute__((packed));

// Read from stream Packet *P = (Packet *)byteStream; if (P->magic != …) …

Page 168: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Member alignment changes to 1

// The load is aligned

// Use Structure Packing to Decrease Expected Alignment

struct Packet { int magic; int payloadLength; char payload[]; } __attribute__((packed));

// Read from stream Packet *P = (Packet *)byteStream; if (P->magic != …) …

Page 169: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Member alignment changes to 1

// This can change structure layout and performance

// The load is aligned

// Use Structure Packing to Decrease Expected Alignment

struct Packet { int magic; int payloadLength; char payload[]; } __attribute__((packed));

// Read from stream Packet *P = (Packet *)byteStream; if (P->magic != …) …

Page 170: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use memcpy() to Perform Unaligned Accesses

struct Packet { int magic; int payloadLength; char payload[]; };

// Read from stream int magic; memcpy(&magic, byteStream + offsetof(struct Packet, magic), sizeof(int)); if (magic != …) …

Page 171: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Use memcpy() to Perform Unaligned Accesses

struct Packet { int magic; int payloadLength; char payload[]; };

// Read from stream int magic; memcpy(&magic, byteStream + offsetof(struct Packet, magic), sizeof(int)); if (magic != …) …

Page 172: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Return value annotated nonnull

Function returns nil anyway

Can cause crashes in mixed C and Swift code

Recommended to opt in to the check

Nonnull Return Value Violation

Page 173: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Nonnull Return Value Violation

@implementation SolarSystem + (nonnull NSDictionary *)planetMoons { return @{@"Earth": @[@"Moon"], @"Mars" : @[@"Phobos", @"Deimos"], // … @"Pluto": @[@"Charon", @"Hydra", @"Nix", @"Kerberos", @"Styx"] }; } - (nonnull NSArray *)moonsOfPlanet:(nonnull NSString *)planet { return [[self class] planetMoons][planet]; } @end

Page 174: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Nonnull Return Value Violation

@implementation SolarSystem + (nonnull NSDictionary *)planetMoons { return @{@"Earth": @[@"Moon"], @"Mars" : @[@"Phobos", @"Deimos"], // … @"Pluto": @[@"Charon", @"Hydra", @"Nix", @"Kerberos", @"Styx"] }; } - (nonnull NSArray *)moonsOfPlanet:(nonnull NSString *)planet { return [[self class] planetMoons][planet]; } @end

Page 175: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Nonnull Return Value Violation

@implementation SolarSystem + (nonnull NSDictionary *)planetMoons { return @{@"Earth": @[@"Moon"], @"Mars" : @[@"Phobos", @"Deimos"], // … }; } - (nonnull NSArray *)moonsOfPlanet:(nonnull NSString *)planet { return [[self class] planetMoons][planet]; } @end

Page 176: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Nonnull Return Value Violation

@implementation SolarSystem + (nonnull NSDictionary *)planetMoons { return @{@"Earth": @[@"Moon"], @"Mars" : @[@"Phobos", @"Deimos"], // … }; } - (nonnull NSArray *)moonsOfPlanet:(nonnull NSString *)planet { return [[self class] planetMoons][planet]; } @end

Page 177: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

// Nonnull Return Value Violation

@implementation SolarSystem + (nonnull NSDictionary *)planetMoons { return @{@"Earth": @[@"Moon"], @"Mars" : @[@"Phobos", @"Deimos"], // … }; } - (nonnull NSArray *)moonsOfPlanet:(nonnull NSString *)planet { return [[self class] planetMoons][planet]; } @end

// Find the biggest moon for each planet NSMutableArray *biggestMoons = [NSMutableArray new]; [biggestMoons addObject:[solarSystem moonsOfPlanet:@"Pluto"][0]];

Page 178: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Null pointer returned from function declared to never return null

// Nonnull Return Value Violation

@implementation SolarSystem + (nonnull NSDictionary *)planetMoons { return @{@"Earth": @[@"Moon"], @"Mars" : @[@"Phobos", @"Deimos"], // … }; } - (nonnull NSArray *)moonsOfPlanet:(nonnull NSString *)planet { return [[self class] planetMoons][planet]; } @end

// Find the biggest moon for each planet NSMutableArray *biggestMoons = [NSMutableArray new]; [biggestMoons addObject:[solarSystem moonsOfPlanet:@"Pluto"][0]];

Page 179: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 180: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking
Page 181: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

•Using Runtime Tools Effectively

Page 182: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

How to Use Runtime Tools Effectively

Exercise more code

Use the tools together

Page 183: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Exercise More Code

Can only catch issues in code that is run

Use runtime tools for daily development

Use them before every release

Avoid spreading bugs to users

Page 184: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Use Continuous Integration

Simplifies testing with runtime tools

Ensures that bugs are caught quickly

Helps track code coverage

Continuous Integration and Code Coverage in Xcode WWDC 2015

Page 185: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Use Runtime Tools Together

Find more issues

Most runtime tools can be used together • Address Sanitizer and Thread Sanitizer are not compatible

Product → Scheme → Edit Scheme… → Diagnostics

Page 186: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Runtime Tool Overhead

Execution overhead Memory overhead

Main Thread Checker 1.02x negligible

Undefined Behavior Sanitizer 1.2x negligible

Address Sanitizer 2–3x 2x

Thread Sanitizer 5–10x 4x

Page 187: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Summary

Xcode 9 enables you to catch critical issues

Use runtime tools early and often

Save time, keep users safe!

Page 188: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Summary

Xcode 9 enables you to catch critical issues

Use runtime tools early and often

Save time, keep users safe!

Page 189: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

More Informationhttps://developer.apple.com/wwdc17/406

Page 190: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Related Sessions

What's New in Swift Tuesday 1:50PM

Debugging with Xcode 9 Wednesday 10:00AM

Modernizing Grand Central Dispatch Usage Wednesday 11:00AM

Understanding Undefined Behavior Executive Ballroom Thursday 9:00AM

What’s New in Testing Hall 2 Thursday 3:10PM

What's New in LLVM Hall 2 Thursday 4:10PM

Page 191: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking

Labs

Performance Profiling and Runtime Analysis Tools Lab Technology Lab K Thu 1:00PM–4:10PM

LLVM Compiler, Objective-C, and C++ Lab Technology Lab E Fri 9:00AM–11:00AM

Page 192: •Finding Bugs Using Xcode Runtime Tools...•Finding Bugs Using Xcode Runtime Tools • Session 406 Developer Tools Improvements in Runtime Checking Improvements in Runtime Checking