SlideShare a Scribd company logo
1 of 47
Download to read offline
Finding & Fixing Memory Leaks
in iOS Apps
                     ©2010 Streaming Colour Studios
Me: Owen Goss
5 years in console games industry
Streaming Colour Studios - Summer 2008
iPhone Games:
      Dapple (Feb 2009)
      Monkeys in Space (Nov 2009)
      LandFormer (Jun 2010)
Chapter on iPhone Debugging
How many of you...
How many of you...

Already have an app in the App Store?
How many of you...

Already have an app in the App Store?
Are working on your first app?
How many of you...

Already have an app in the App Store?
Are working on your first app?
Are a Mac OS X developer?
How many of you...

Already have an app in the App Store?
Are working on your first app?
Are a Mac OS X developer?
Have never touched Objective-C before?
Don’t worry...
     www.streamingcolour.com/blog




This presentation and the example code I present will all be made available after the
conference on my blog.
The Plan, Man

          What’s a Memory Leak
          Retain, Release & Stuff
          Common Leaks
          Finding & Fixing Leaks



-   To start, I’ll talk specifically about what a leak is
-   I’ll give an overview of memory management in iOS
-   I’ll go through some common ways to introduce leaks
-   We’ll jump into Xcode with some sample code and actually find and fix a bunch of leaks.
What is a Memory Leak?




In order to talk about how memory leaks occur, how to fix them, and why they’re bad, we
first need to define what they are.
A memory leak is a piece of
     allocated memory that
     nothing points to.


There are two important things here: 1) we’re talking about heap memory, or memory that’s
allocated. Think: pointers. 2) We’re talking about a chunk of memory that’s “lost” on the
heap. Nothing references it anymore.
What’s a Leak?
                                                                  Heap (memory)



    // a = 0x0032ba80
    MyClass* a = [[MyClass alloc] init];

    // OR in C++
    // MyClass* a = new MyClass();

    // OR in C
    // MyStruct* a = (MyStruct*)malloc(sizeof(MyStruct));




The previous slide stated that a leak involves a piece of allocated memory. This is how we
allocate memory in Obj-C (and examples in C++ and C). This takes a chunk of heap memory
of the size of our object and says “This memory is reserved”. The pointer, a, is just a number
that stores the address of the object in memory so we can find it.
What’s a Leak?
                                                                      0x0
                                                                      ...




    // Memory leak!
    a = nil;




But if you change the value of the pointer, to point to say, nil, then the chunk of memory we
allocated can no longer be found. However, no one told the OS that it could be freed, so it’s
still there with no way to be cleaned up. This is a leak.
The good news
    No shared memory means you can’t leak
    system-wide memory




You can’t leak OS-wide memory on the iPhone.
The good news
     On exit ➟ app memory cleaned up




All memory you allocate during execution of your app is freed by the system when your app
shuts down. This includes any leaks you introduce.
The worst-case
     You cause your own app to crash




In the worst-case, your leaks will cause you to run out of free memory and your app will
crash. Obviously this is a bad thing, but you can’t kill the OS with your leaks.
Retain, Release
     & Stuff




Give a quick overview of memory management in iOS: retain & release
Stuff because we’ll talk about hidden retains, and some stuff like autorelease
iOS ➟ No Garbage Collection




For the Mac OS X/scripting language programmers in the room.
But...


Objects are reference counted

         um... sort of...
          if done right
NSObject has a property:
     retainCount



Since all NS* and UI* classes in iOS are derived from NSObject, they also have retainCount.
Any classes you create that subclass NSObject have a retainCount.
But what does retainCount do?
if retainCount == 0
    	 the object will be freed



The iOS memory manager uses the retainCount to determine when to free allocated memory.
If the retainCount becomes 0, the memory is freed.
retain/release

      [objectA retain] //objectA.retainCount++




      [objectA release] //objectA.retainCount--




At its most basic, calling retain on an object pointer increases the retainCount by 1. Calling
release decreases it by one. It gets more complicated, as we’ll see, but this is at the root of it
all. This is what you MUST understand about memory in iOS.
retain/release                                                   A.retainCount

                          B                   A                                    1


                          B                   A                   C                2


                          B                   A                   C                1


                          B                   A                                    0

Here we see some object A has been allocated in memory. Object B retains it with some
pointer. Then object C also retains it with its pointer. The retain count is 2 once both B & C
hold pointers to it. In order for A to get cleaned up, both B & C must release their pointers to
A.
If you retain, you must release




So remember: retain increases the retainCount by one, release decreases the retainCount by
1. When the retainCount is 0, the object is freed. If you take one thing away from this talk, it
is this. Think of it like parentheses that must always match.
“Hidden” retain/release




Here’s where things get a little more complicated. We saw before that calling retain on a
pointer to an NSObject increases the retainCount, but there are calls in Obj-C that increase
the retainCount “secretly”, or at least, quietly.
alloc

    // objectA.retainCount = 1
    MyClass* objectA = [[MyClass alloc] init];

    ...

    // objectA.retainCount = 0
    // free the memory
    [objectA release];




Let’s start at the beginning. The way you allocated memory for an object, in general, in
Objective-C is with the “alloc” method. This is like calling new() in C++ or malloc() in C, but
it’s reference counted. When you make an alloc call, it does an IMPLICIT retain on the pointer.
Objects that are alloc’ed must be released at some point.
retain Property Attribute

     @interface MyClass : NSObject {
        NSObject* objectA;
     }

     @property (nonatomic, retain) NSObject* objectA;

     @end




Here we have a class called MyClass that has a property declaration for an NSObject instance
called objectA. Note the retain property attribute.
retain Property Attribute
    // @property (nonatomic, retain) NSObject* objectA;

    @implementation MyClass

    @synthesize objectA;
    ...

          // objectA now points to objectB, and
          // objectB.retainCount++
          self.objectA = objectB;
          // Equiv to: [self setObjectA:objectB];

    ...
    @end


Note the use of the “self” keyword. This says that you want to use the property’s accessors to
set the value of objectA. This is the same as calling [self setObjectA:objectB]. This is NOT just
doing an assignment!
self.objectA = objectB;

    // @property (nonatomic, retain) NSObject* objectA;

    // It’s doing something like this...
    - (void)setObjectA:(NSObject*)objectB {
       [objectA release];
       objectA = objectB;
       [objectA retain];
    }




When you do this, two things happen: 1) if objectA was holding a reference to some object,
that object gets an IMPLICIT release called on it. 2) an IMPLICIT retain is done on the new
object (objectB)!
retain Property Attribute

    // @property (nonatomic, retain) NSObject* objectA;

         // objectB.retainCount++
         self.objectA = objectB;


         // NO RETAIN IS DONE!
         objectA = objectB;




If you assign an object pointer to another WITHOUT the self keyword, the accessor of the
property is NOT used, and therefore NO retain is done! When you omit the self keyword, only
an assignment is done.
retain Property Attribute

    // @property (nonatomic, retain) NSObject* objectA;

          // objectA.retainCount--
          self.objectA = nil;


          // NO RELEASE IS DONE!
          // Potential Memory Leak!
          objectA = nil;




Similarly, using the self keyword to set an object to nil does an IMPLICIT release on the
object. But watch out, setting a pointer to nil without the self keyword COULD cause a
memory leak.
autorelease pools




Autorelease pools are collections of objects. They exist in a stack of pools. When you call the
autorelease method on an object, the object gets added to the top autorelease pool. Read the
Apple documentation on Autorelease pools for more information.
autorelease pools
                       on autorealese pool dealloc:




But an autorelease pool is an object itself. When it gets deallocated, it calls release on every
object inside it. iOS creates an autorelease pool every time through the run loop, and releases
it at the end (as well as at other points during execution, like touch events - see Apple docs).
autorelease pools

    - (MyClass*) getNewMyClass {
       // mc.retainCount = 1
       MyClass* mc = [[MyClass alloc] init];

         // When the current autorelease pool gets
         // dealloc’ed, the retainCount will decrease
         return [mc autorelease];
    }




Here’s a good way to use autorelease in an iOS app: returning an allocated object. The calling
code can choose to retain the returned object if it wants to keep it long-term. But if it only
needs it right now, it can just use it and ignore it, and the autorelease pool will clean it up
later. Calling code doesn’t need to worry about it.
NSMutableArray (e.g.)

    NSMutableArray* array = [NSMutableArray array];

    // objectA.retainCount = 1
    MyClass* objectA = [[MyClass alloc] init];
    // objectA.retainCount = 2
    [array addObject:objectA];




Lots of container class methods will retain your objects for you. This is almost always the
desired behaviour. Just remember that in order to decrease your retainCount, your object
either needs to be removed from the array, or the array needs to be destroyed. Read the
docs! Know what retains, what doesn’t.
NSMutableArray (e.g.)

    NSMutableArray* array = [NSMutableArray array];

    // objectA.retainCount = 1
    MyClass* objectA = [[MyClass alloc] init];
    // objectA.retainCount = 2
    [array addObject:objectA];



                  Lesson: Read the documentation!


Lots of container class methods will retain your objects for you. This is almost always the
desired behaviour. Just remember that in order to decrease your retainCount, your object
either needs to be removed from the array, or the array needs to be destroyed. Read the
docs! Know what retains, what doesn’t.
alloc-init vs. other

     // array1.retainCount = 1
     // You must release to free it
     NSArray* array1 = [[NSArray alloc] init];

     // array2 is autoreleased
     // You must retain to hold on to it
     NSArray* array2 = [NSArray array];




Most of the built-in classes in iOS have two versions of initializers. One version will start with
init*, while the other starts with the class name (e.g. array, string, dictionary). The init
function always requires an alloc (and that alloc does the implicit retain). The other returns a
new object that is autoreleased.
All Clear?
Moving on...
Some Common Leaks




Let’s take a look at some common memory leaks and how to fix them. Once we’ve gone
through these, we’ll jump into Xcode and the Leaks tool and do it for real.
Leak
    // @property (nonatomic, retain) MyClass* objectA;

    - (void)foo {
       // retainCount = 2
       self.objectA = [[MyClass alloc] init];
    }

    -(void)dealloc {
       // retainCount = 1
       [objectA release];
       [super dealloc];
    }



Note that the line in foo actually does 2 retains (self. and alloc). This object will leak objectA
when it gets dealloc’ed. When the object gets cleaned up, objectA still has a retainCount of 1,
but nothing will be pointing to it anymore: leak.
Leak Fixed
    // @property (nonatomic, retain) MyClass* objectA;

    - (void)foo {
       // retainCount                = 1
       MyClass* obj =                [[MyClass alloc] init];
       // retainCount                = 2
       self.objectA =                obj;
       // retainCount                = 1
       [obj release];
    }

    -(void)dealloc {
       // retainCount = 0
       [objectA release];
       [super dealloc];
    }
2 retains, 2 releases = leak fixed.
Leak
    // @property (nonatomic, retain) MyClass* objectA;

    - (void)foo {
       MyClass* obj = [[MyClass alloc] init];
       self.objectA = obj;
       [obj release];
       // retainCount = 1
    }

    -(void)dealloc {
       // retainCount = 1
       [super dealloc];
    }



So here we’ve done everything right...but oops! Forgot the release call in the dealloc method.
This is probably the most common leak you will encounter in your code, but luckily it’s the
easiest to fix.
Leak Fixed
    // @property (nonatomic, retain) MyClass* objectA;

    - (void)foo {
       MyClass* obj = [[MyClass alloc] init];
       self.objectA = obj;
       [obj release];
       // retainCount = 1
    }

    -(void)dealloc {
       // retainCount = 0
       [objectA release];
       [super dealloc];
    }

2 retains, 2 releases = leak fixed.
Build & Analyze
     Try it, it might work for you.*




                                                          * or wait for Xcode 4

Build & Analyze is a build option in Xcode that runs the CLANG static analyzer. It can
sometimes pick up memory leaks in your code at compile time! I’ve never had much luck
getting it to work properly in Xcode 3.x, but give it a try in Xcode 4.
Leaks Instrument
     Leaks will show you the allocation that leaks. It’s
     up to you to figure out why it wasn’t released.




This is what you need to understand about the Leaks tool. It’s an amazing tool, but it can’t
do everything for you. You still need to understand your own code and how memory
management works.
Xcode Time!
     http://streamingcolour.com/presentations/
     memLeakExampleProject.zip




Now that we’ve got all that under our belts, I’m going to jump into Xcode, boot up the Leaks
Instrument and show you how to find these things for real. Download the project here:
http://streamingcolour.com/presentations/memLeakExampleProject.zip
Fin.
Questions.
twitter: @OwenGoss
email: owen.goss@streamingcolour.com
web: www.streamingcolour.com

More Related Content

Viewers also liked

QUẢN LÍ BỘ NHỚ KHI LẬP TRÌNH APPLE iOS
QUẢN LÍ BỘ NHỚ KHI LẬP TRÌNH APPLE iOSQUẢN LÍ BỘ NHỚ KHI LẬP TRÌNH APPLE iOS
QUẢN LÍ BỘ NHỚ KHI LẬP TRÌNH APPLE iOSwe20
 
Quản lý bộ nhớ trong khi phát triển ứng dụng Apple iOS
Quản lý bộ nhớ trong khi phát triển ứng dụng Apple iOSQuản lý bộ nhớ trong khi phát triển ứng dụng Apple iOS
Quản lý bộ nhớ trong khi phát triển ứng dụng Apple iOSaction.vn
 
Memory management in Objective C
Memory management in Objective CMemory management in Objective C
Memory management in Objective CNeha Gupta
 
Advanced Memory Management on iOS and Android - Mark Probst and Rodrigo Kumpera
Advanced Memory Management on iOS and Android - Mark Probst and Rodrigo KumperaAdvanced Memory Management on iOS and Android - Mark Probst and Rodrigo Kumpera
Advanced Memory Management on iOS and Android - Mark Probst and Rodrigo KumperaXamarin
 
CS193P Lecture 5 View Animation
CS193P Lecture 5 View AnimationCS193P Lecture 5 View Animation
CS193P Lecture 5 View Animationonoaonoa
 
Deep Parameters Tuning for Android Mobile Apps
Deep Parameters Tuning for Android Mobile AppsDeep Parameters Tuning for Android Mobile Apps
Deep Parameters Tuning for Android Mobile AppsDavide De Chiara
 
iOS Developer Overview - DevWeek 2014
iOS Developer Overview - DevWeek 2014iOS Developer Overview - DevWeek 2014
iOS Developer Overview - DevWeek 2014Paul Ardeleanu
 
Tuning Android Applications (Part One)
Tuning Android Applications (Part One)Tuning Android Applications (Part One)
Tuning Android Applications (Part One)CommonsWare
 
Android performance tuning. Memory.
Android performance tuning. Memory.Android performance tuning. Memory.
Android performance tuning. Memory.Sergii Kozyrev
 
Objective-C for Java developers
Objective-C for Java developersObjective-C for Java developers
Objective-C for Java developersFábio Bernardo
 
Tuning android for low ram devices
Tuning android for low ram devicesTuning android for low ram devices
Tuning android for low ram devicesDroidcon Berlin
 
Android Performance Best Practices
Android Performance Best Practices Android Performance Best Practices
Android Performance Best Practices Amgad Muhammad
 
Objective-C for Java Developers
Objective-C for Java DevelopersObjective-C for Java Developers
Objective-C for Java DevelopersBob McCune
 
Java Garbage Collection, Monitoring, and Tuning
Java Garbage Collection, Monitoring, and TuningJava Garbage Collection, Monitoring, and Tuning
Java Garbage Collection, Monitoring, and TuningCarol McDonald
 
Jvm Performance Tunning
Jvm Performance TunningJvm Performance Tunning
Jvm Performance TunningTerry Cho
 
What is reactive programming?
What is reactive programming?What is reactive programming?
What is reactive programming?Kenji Tanaka
 
Layer architecture of ios (1)
Layer architecture of ios (1)Layer architecture of ios (1)
Layer architecture of ios (1)dwipalp
 

Viewers also liked (20)

QUẢN LÍ BỘ NHỚ KHI LẬP TRÌNH APPLE iOS
QUẢN LÍ BỘ NHỚ KHI LẬP TRÌNH APPLE iOSQUẢN LÍ BỘ NHỚ KHI LẬP TRÌNH APPLE iOS
QUẢN LÍ BỘ NHỚ KHI LẬP TRÌNH APPLE iOS
 
Objective C Memory Management
Objective C Memory ManagementObjective C Memory Management
Objective C Memory Management
 
Quản lý bộ nhớ trong khi phát triển ứng dụng Apple iOS
Quản lý bộ nhớ trong khi phát triển ứng dụng Apple iOSQuản lý bộ nhớ trong khi phát triển ứng dụng Apple iOS
Quản lý bộ nhớ trong khi phát triển ứng dụng Apple iOS
 
Memory management in Objective C
Memory management in Objective CMemory management in Objective C
Memory management in Objective C
 
iOS Basic
iOS BasiciOS Basic
iOS Basic
 
Advanced Memory Management on iOS and Android - Mark Probst and Rodrigo Kumpera
Advanced Memory Management on iOS and Android - Mark Probst and Rodrigo KumperaAdvanced Memory Management on iOS and Android - Mark Probst and Rodrigo Kumpera
Advanced Memory Management on iOS and Android - Mark Probst and Rodrigo Kumpera
 
CS193P Lecture 5 View Animation
CS193P Lecture 5 View AnimationCS193P Lecture 5 View Animation
CS193P Lecture 5 View Animation
 
iOS Memory Management
iOS Memory ManagementiOS Memory Management
iOS Memory Management
 
Deep Parameters Tuning for Android Mobile Apps
Deep Parameters Tuning for Android Mobile AppsDeep Parameters Tuning for Android Mobile Apps
Deep Parameters Tuning for Android Mobile Apps
 
iOS Developer Overview - DevWeek 2014
iOS Developer Overview - DevWeek 2014iOS Developer Overview - DevWeek 2014
iOS Developer Overview - DevWeek 2014
 
Tuning Android Applications (Part One)
Tuning Android Applications (Part One)Tuning Android Applications (Part One)
Tuning Android Applications (Part One)
 
Android performance tuning. Memory.
Android performance tuning. Memory.Android performance tuning. Memory.
Android performance tuning. Memory.
 
Objective-C for Java developers
Objective-C for Java developersObjective-C for Java developers
Objective-C for Java developers
 
Tuning android for low ram devices
Tuning android for low ram devicesTuning android for low ram devices
Tuning android for low ram devices
 
Android Performance Best Practices
Android Performance Best Practices Android Performance Best Practices
Android Performance Best Practices
 
Objective-C for Java Developers
Objective-C for Java DevelopersObjective-C for Java Developers
Objective-C for Java Developers
 
Java Garbage Collection, Monitoring, and Tuning
Java Garbage Collection, Monitoring, and TuningJava Garbage Collection, Monitoring, and Tuning
Java Garbage Collection, Monitoring, and Tuning
 
Jvm Performance Tunning
Jvm Performance TunningJvm Performance Tunning
Jvm Performance Tunning
 
What is reactive programming?
What is reactive programming?What is reactive programming?
What is reactive programming?
 
Layer architecture of ios (1)
Layer architecture of ios (1)Layer architecture of ios (1)
Layer architecture of ios (1)
 

Recently uploaded

How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 

Recently uploaded (20)

How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 

Finding and Fixing Memory Leaks in iOS Apps

  • 1. Finding & Fixing Memory Leaks in iOS Apps ©2010 Streaming Colour Studios
  • 2. Me: Owen Goss 5 years in console games industry Streaming Colour Studios - Summer 2008 iPhone Games: Dapple (Feb 2009) Monkeys in Space (Nov 2009) LandFormer (Jun 2010) Chapter on iPhone Debugging
  • 3. How many of you...
  • 4. How many of you... Already have an app in the App Store?
  • 5. How many of you... Already have an app in the App Store? Are working on your first app?
  • 6. How many of you... Already have an app in the App Store? Are working on your first app? Are a Mac OS X developer?
  • 7. How many of you... Already have an app in the App Store? Are working on your first app? Are a Mac OS X developer? Have never touched Objective-C before?
  • 8. Don’t worry... www.streamingcolour.com/blog This presentation and the example code I present will all be made available after the conference on my blog.
  • 9. The Plan, Man What’s a Memory Leak Retain, Release & Stuff Common Leaks Finding & Fixing Leaks - To start, I’ll talk specifically about what a leak is - I’ll give an overview of memory management in iOS - I’ll go through some common ways to introduce leaks - We’ll jump into Xcode with some sample code and actually find and fix a bunch of leaks.
  • 10. What is a Memory Leak? In order to talk about how memory leaks occur, how to fix them, and why they’re bad, we first need to define what they are.
  • 11. A memory leak is a piece of allocated memory that nothing points to. There are two important things here: 1) we’re talking about heap memory, or memory that’s allocated. Think: pointers. 2) We’re talking about a chunk of memory that’s “lost” on the heap. Nothing references it anymore.
  • 12. What’s a Leak? Heap (memory) // a = 0x0032ba80 MyClass* a = [[MyClass alloc] init]; // OR in C++ // MyClass* a = new MyClass(); // OR in C // MyStruct* a = (MyStruct*)malloc(sizeof(MyStruct)); The previous slide stated that a leak involves a piece of allocated memory. This is how we allocate memory in Obj-C (and examples in C++ and C). This takes a chunk of heap memory of the size of our object and says “This memory is reserved”. The pointer, a, is just a number that stores the address of the object in memory so we can find it.
  • 13. What’s a Leak? 0x0 ... // Memory leak! a = nil; But if you change the value of the pointer, to point to say, nil, then the chunk of memory we allocated can no longer be found. However, no one told the OS that it could be freed, so it’s still there with no way to be cleaned up. This is a leak.
  • 14. The good news No shared memory means you can’t leak system-wide memory You can’t leak OS-wide memory on the iPhone.
  • 15. The good news On exit ➟ app memory cleaned up All memory you allocate during execution of your app is freed by the system when your app shuts down. This includes any leaks you introduce.
  • 16. The worst-case You cause your own app to crash In the worst-case, your leaks will cause you to run out of free memory and your app will crash. Obviously this is a bad thing, but you can’t kill the OS with your leaks.
  • 17. Retain, Release & Stuff Give a quick overview of memory management in iOS: retain & release Stuff because we’ll talk about hidden retains, and some stuff like autorelease
  • 18. iOS ➟ No Garbage Collection For the Mac OS X/scripting language programmers in the room.
  • 19. But... Objects are reference counted um... sort of... if done right
  • 20. NSObject has a property: retainCount Since all NS* and UI* classes in iOS are derived from NSObject, they also have retainCount. Any classes you create that subclass NSObject have a retainCount. But what does retainCount do?
  • 21. if retainCount == 0 the object will be freed The iOS memory manager uses the retainCount to determine when to free allocated memory. If the retainCount becomes 0, the memory is freed.
  • 22. retain/release [objectA retain] //objectA.retainCount++ [objectA release] //objectA.retainCount-- At its most basic, calling retain on an object pointer increases the retainCount by 1. Calling release decreases it by one. It gets more complicated, as we’ll see, but this is at the root of it all. This is what you MUST understand about memory in iOS.
  • 23. retain/release A.retainCount B A 1 B A C 2 B A C 1 B A 0 Here we see some object A has been allocated in memory. Object B retains it with some pointer. Then object C also retains it with its pointer. The retain count is 2 once both B & C hold pointers to it. In order for A to get cleaned up, both B & C must release their pointers to A.
  • 24. If you retain, you must release So remember: retain increases the retainCount by one, release decreases the retainCount by 1. When the retainCount is 0, the object is freed. If you take one thing away from this talk, it is this. Think of it like parentheses that must always match.
  • 25. “Hidden” retain/release Here’s where things get a little more complicated. We saw before that calling retain on a pointer to an NSObject increases the retainCount, but there are calls in Obj-C that increase the retainCount “secretly”, or at least, quietly.
  • 26. alloc // objectA.retainCount = 1 MyClass* objectA = [[MyClass alloc] init]; ... // objectA.retainCount = 0 // free the memory [objectA release]; Let’s start at the beginning. The way you allocated memory for an object, in general, in Objective-C is with the “alloc” method. This is like calling new() in C++ or malloc() in C, but it’s reference counted. When you make an alloc call, it does an IMPLICIT retain on the pointer. Objects that are alloc’ed must be released at some point.
  • 27. retain Property Attribute @interface MyClass : NSObject { NSObject* objectA; } @property (nonatomic, retain) NSObject* objectA; @end Here we have a class called MyClass that has a property declaration for an NSObject instance called objectA. Note the retain property attribute.
  • 28. retain Property Attribute // @property (nonatomic, retain) NSObject* objectA; @implementation MyClass @synthesize objectA; ... // objectA now points to objectB, and // objectB.retainCount++ self.objectA = objectB; // Equiv to: [self setObjectA:objectB]; ... @end Note the use of the “self” keyword. This says that you want to use the property’s accessors to set the value of objectA. This is the same as calling [self setObjectA:objectB]. This is NOT just doing an assignment!
  • 29. self.objectA = objectB; // @property (nonatomic, retain) NSObject* objectA; // It’s doing something like this... - (void)setObjectA:(NSObject*)objectB { [objectA release]; objectA = objectB; [objectA retain]; } When you do this, two things happen: 1) if objectA was holding a reference to some object, that object gets an IMPLICIT release called on it. 2) an IMPLICIT retain is done on the new object (objectB)!
  • 30. retain Property Attribute // @property (nonatomic, retain) NSObject* objectA; // objectB.retainCount++ self.objectA = objectB; // NO RETAIN IS DONE! objectA = objectB; If you assign an object pointer to another WITHOUT the self keyword, the accessor of the property is NOT used, and therefore NO retain is done! When you omit the self keyword, only an assignment is done.
  • 31. retain Property Attribute // @property (nonatomic, retain) NSObject* objectA; // objectA.retainCount-- self.objectA = nil; // NO RELEASE IS DONE! // Potential Memory Leak! objectA = nil; Similarly, using the self keyword to set an object to nil does an IMPLICIT release on the object. But watch out, setting a pointer to nil without the self keyword COULD cause a memory leak.
  • 32. autorelease pools Autorelease pools are collections of objects. They exist in a stack of pools. When you call the autorelease method on an object, the object gets added to the top autorelease pool. Read the Apple documentation on Autorelease pools for more information.
  • 33. autorelease pools on autorealese pool dealloc: But an autorelease pool is an object itself. When it gets deallocated, it calls release on every object inside it. iOS creates an autorelease pool every time through the run loop, and releases it at the end (as well as at other points during execution, like touch events - see Apple docs).
  • 34. autorelease pools - (MyClass*) getNewMyClass { // mc.retainCount = 1 MyClass* mc = [[MyClass alloc] init]; // When the current autorelease pool gets // dealloc’ed, the retainCount will decrease return [mc autorelease]; } Here’s a good way to use autorelease in an iOS app: returning an allocated object. The calling code can choose to retain the returned object if it wants to keep it long-term. But if it only needs it right now, it can just use it and ignore it, and the autorelease pool will clean it up later. Calling code doesn’t need to worry about it.
  • 35. NSMutableArray (e.g.) NSMutableArray* array = [NSMutableArray array]; // objectA.retainCount = 1 MyClass* objectA = [[MyClass alloc] init]; // objectA.retainCount = 2 [array addObject:objectA]; Lots of container class methods will retain your objects for you. This is almost always the desired behaviour. Just remember that in order to decrease your retainCount, your object either needs to be removed from the array, or the array needs to be destroyed. Read the docs! Know what retains, what doesn’t.
  • 36. NSMutableArray (e.g.) NSMutableArray* array = [NSMutableArray array]; // objectA.retainCount = 1 MyClass* objectA = [[MyClass alloc] init]; // objectA.retainCount = 2 [array addObject:objectA]; Lesson: Read the documentation! Lots of container class methods will retain your objects for you. This is almost always the desired behaviour. Just remember that in order to decrease your retainCount, your object either needs to be removed from the array, or the array needs to be destroyed. Read the docs! Know what retains, what doesn’t.
  • 37. alloc-init vs. other // array1.retainCount = 1 // You must release to free it NSArray* array1 = [[NSArray alloc] init]; // array2 is autoreleased // You must retain to hold on to it NSArray* array2 = [NSArray array]; Most of the built-in classes in iOS have two versions of initializers. One version will start with init*, while the other starts with the class name (e.g. array, string, dictionary). The init function always requires an alloc (and that alloc does the implicit retain). The other returns a new object that is autoreleased.
  • 39. Some Common Leaks Let’s take a look at some common memory leaks and how to fix them. Once we’ve gone through these, we’ll jump into Xcode and the Leaks tool and do it for real.
  • 40. Leak // @property (nonatomic, retain) MyClass* objectA; - (void)foo { // retainCount = 2 self.objectA = [[MyClass alloc] init]; } -(void)dealloc { // retainCount = 1 [objectA release]; [super dealloc]; } Note that the line in foo actually does 2 retains (self. and alloc). This object will leak objectA when it gets dealloc’ed. When the object gets cleaned up, objectA still has a retainCount of 1, but nothing will be pointing to it anymore: leak.
  • 41. Leak Fixed // @property (nonatomic, retain) MyClass* objectA; - (void)foo { // retainCount = 1 MyClass* obj = [[MyClass alloc] init]; // retainCount = 2 self.objectA = obj; // retainCount = 1 [obj release]; } -(void)dealloc { // retainCount = 0 [objectA release]; [super dealloc]; } 2 retains, 2 releases = leak fixed.
  • 42. Leak // @property (nonatomic, retain) MyClass* objectA; - (void)foo { MyClass* obj = [[MyClass alloc] init]; self.objectA = obj; [obj release]; // retainCount = 1 } -(void)dealloc { // retainCount = 1 [super dealloc]; } So here we’ve done everything right...but oops! Forgot the release call in the dealloc method. This is probably the most common leak you will encounter in your code, but luckily it’s the easiest to fix.
  • 43. Leak Fixed // @property (nonatomic, retain) MyClass* objectA; - (void)foo { MyClass* obj = [[MyClass alloc] init]; self.objectA = obj; [obj release]; // retainCount = 1 } -(void)dealloc { // retainCount = 0 [objectA release]; [super dealloc]; } 2 retains, 2 releases = leak fixed.
  • 44. Build & Analyze Try it, it might work for you.* * or wait for Xcode 4 Build & Analyze is a build option in Xcode that runs the CLANG static analyzer. It can sometimes pick up memory leaks in your code at compile time! I’ve never had much luck getting it to work properly in Xcode 3.x, but give it a try in Xcode 4.
  • 45. Leaks Instrument Leaks will show you the allocation that leaks. It’s up to you to figure out why it wasn’t released. This is what you need to understand about the Leaks tool. It’s an amazing tool, but it can’t do everything for you. You still need to understand your own code and how memory management works.
  • 46. Xcode Time! http://streamingcolour.com/presentations/ memLeakExampleProject.zip Now that we’ve got all that under our belts, I’m going to jump into Xcode, boot up the Leaks Instrument and show you how to find these things for real. Download the project here: http://streamingcolour.com/presentations/memLeakExampleProject.zip