Login | Register   
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Performing Code Analysis on your iPhone Applications

In Xcode 3.2, Apple has integrated Clang, a source code analysis tool that finds bugs in C and Objective-C programs.


advertisement
One of the key challenges faced by iPhone developers is in the area of memory management. If you are coming from an environment where memory management is all done for you via the garbage collector, the iPhone development platform could be quite a challenge to get used to.

Prior to Xcode 3.2, most developers used an open-source tool known as Clang, a source code analysis tool that finds bugs in C and Objective-C programs, to locate memory leaks in their iPhone applications. Using Clang, you could find potential code statements that could result in memory leaks, as well as find buggy code blocks that might cause runtime errors.

In Xcode 3.2, Apple has integrated Clang into the Xcode IDE, making it easily available to developers without the detailed configurations steps needed to configure Clang. This article takes you through some of the capabilities of Clang.



Memory Leaks

The most common use of Clang is to detect memory leaks in your application. For this purpose, launch Xcode and create a new View-based Application project. Name it Analyzer. In the AnalyzerViewController.m file, add the following statements in bold:

#import "AnalyzerViewController.h" @implementation AnalyzerViewController -(void) doSomething { NSString *str = [[NSString alloc] initWithString:@"This is a string"]; }

To build the project and analyze the code at the same time, select Build'Build and Analyzer. You will see that Xcode now displays a blue-color icons containing two arrows (see Figure 1).

Figure 1. The message displayed by Clang.

It indicates that there is a potential memory leak of an object created and then stored into the variable called str. If you click on the icon, you will see the message shown in Figure 2.

Figure 2. Detailed message displayed by Clang.

The above code generates a warning because the str is allocated an NSString object, but it was never released before the method exits. To fix the problem, simply add a release statement:

-(void) doSomething { NSString *str = [[NSString alloc] initWithString:@"This is a string"]; [str release]; }

Let's take a look at another example. This time, code the doSomething method as follows:

-(void) doSomething { NSString *str = [NSString stringWithString:@"This is a string"]; [str release]; }

This time round, str is initialized with an auto-release string constant, which means that you do not own the object and hence cannot release it manually. If you now select the Build and Analyze menu item again, you will see the warning message as shown in Figure 3.

Figure 3. Incorrectly releasing an autorelease object.

To fix the error, simply remove the release statement:

-(void) doSomething { NSString *str = [NSString stringWithString:@"This is a string"]; // [str release]; }

Interesting Things about Strings

Dealing with strings in Objective-C is sometimes like opening a Pandora box - you never know what you are going to get. Consider the following example:

#import "AnalyzerViewController.h" @implementation AnalyzerViewController -(void) doSomething { NSString *str = [[NSString alloc] initWithString:@"This is a string"]; str = [[NSString alloc] initWithString:@"This is another string"]; [str release]; }

Look at the code above carefully. Is there a memory leak? Now, select the Build and Analyze menu item and see the result of the analysis. You should see the result shown in Figure 4.

Figure 4. Clang detecting a potential memory leak.

In fact, there is a memory leak. The first statement assigns str to an NSString object. And the second statement allocates another instance of the NSString object. The release statement releases the second NSString object. However, the first NSString object is leaked and it will never be recovered. Hence there is a memory leak. Consider a slightly changed version of the same code:

-(void) doSomething { NSString *str = [[NSString alloc] initWithString:@"This is a string"]; str = [[NSString alloc] initWithString:@"This is a string"]; [str release]; }

If you get the compiler to analyze the code again, notice that it will continue to sound off a warning about potential memory leaks. However, observe carefully that both strings now contain the same string constant. When two objects have the same string constant, the compiler will assign the two variables to point to only one instance. To verify this, you can print out the address of the two variables, like this:

-(void) doSomething { NSString *str = [[NSString alloc] initWithString:@"This is a string"]; NSLog(@"%d", str); str = [[NSString alloc] initWithString:@"This is an string"]; NSLog(@"%d", str); [str release]; }

If you were to run the above code, you will see that the address is the same for both. If you change the two strings to be different, you would then see different addresses.

Hence, to conclude, in this case, if the two strings are the same, there will be no memory leaks. In general, it is wise to be careful about such cases and follow the rule-of-thumb for memory management in Objective-C - release whenever you use an alloc.

Let's consider another example:

-(void) doSomething { NSString *str2; for (int i = 0; i < 50; i++){ NSString *str1 = @"This is a constant string"; str2 = [[NSString alloc] initWithString:str1]; } [str2 release]; }

When you analyze the code, you will see the message as shown in Figure 5.

Figure 5. Clang sounding a memory leak warning.

Again, in this case there is no memory leak. The str1 object is an auto-release object while str2 always get assigned the same string constant. Printing out the addresses of str1 and str2 confirms this:

-(void) doSomething { NSString *str2; for (int i = 0; i < 50; i++){ NSString *str1 = @"This is a constant string"; NSLog(@"str1 address is %d", str1); str2 = [[NSString alloc] initWithString:str1]; NSLog(@"str2 address is %d", str2); } [str2 release]; }

Figure 6 shows the output observed in the Debugger Console window.

Figure 6. The addresses of the objects as printed out in the Debugger Console window


Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap