I want to ask some question about the iPhone or objective C. What is 'garbage collected environment'? Thank you very much.
Expanding on Mr. Witherspoon's answer, you must alloc (allocate) and release memory space for some objects in your code. To practice good memory management, anything you have an alloc for you must have a matching release. For example:
NSString *string = [[NSString alloc]initWithFormat:#"%#", something];
/* ... some code ... */
[string release];
As you can see, my string is allocated some memory space but I release it programmatically when I won't need it anymore.
Garbage collection is a feature of the Objective-C runtime on the Mac and is not yet available on the iPhone. There, it basically means that you don't have to worry as much about memory management and handling retain / release cycles.
Related
I'm just investigating some memory leaks in my app, I'm using Xcode 4.0.2. I've run the Analyze tool in Xcode and a good few memory leaks have been identified. I'm relatively new to Objective-C, this is my first app. I've pasted the code here:
http://pastie.org/3155043
I've added comments to the above code, where the memory leaks are occuring.
Memory Leak One: Method returns an Objective-C object with a +1 retain count (owning reference).
Memory Leak Two: Object allocated on line 248 and stored in 'imagesNames' is not referenced later in this execution path and has a retain count of +1 (object leaked).
Memory Leak Three: Potential leak of an object allocated on line 246 and stored into 'cmpWordoutStr'.
Any help appreciated.
Regards,
Stephen
You might want to consider using Automatic Reference Counting in your project.
I asked a question the other day on here, as I wasn't sure that it was a good idea, but the answers convinced me that it really is a step forward and is well worth taking advantage of:
To ARC or not to ARC? What are the pros and cons?
Hope this helps :)
Leak 1) You don't show the return or identify which variable is returned, so not possible to definitively diagnose this one.
Leak 2) You alloc/init an NSString and assign it to a variable that is never released. This is wrong for two reasons:
For each alloc there must be a corresponding release somewhere.
There is no point in doing alloc/init on an empty string. If you want an empty string just use #"".
Leak 3) Basically the same as (2).
(You really need to get a good book on Objective-C programming and study and restudy the section on storage management. Otherwise you'll be stumbling around in the dark.)
You're allocating an object first
NSString *cmpWorkoutStr = [[NSString alloc] init];
and then reassign the pointer without freeing the memory:
cmpWorkoutStr = [cmpWorkoutStr stringByAppendingString:indWorkoutStr];
hence the leak.
I didn't analyze your code in depth, but I guess you actually want NSMutableString there.
As Tom Andersen suggested above I used auto release and this solved the problem, example below:
NSString *cmpWorkoutStr = [[[NSString alloc] init] autorelease];
NSString *imageNames = [[[NSString alloc] init] autorelease];
Regards,
Stephen
Suppose there is a string of type NSSTring
NSString *string;
There is array called testArray, which is array of string objects
string=[testArray objectAtIndex:1];
Do we need to give
[string release]
or not?
No, You needn't do
[string release]
You must release object only if you allocate memory for it. Check this Memory Management Policy for more detail information about alloc and release.
no .. in this case not.
if you get a string from a function, it has usually the autorelease flag and will get released later.
You need to release it if you retain it, if you alloc it or copy it.
You should read: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html#//apple_ref/doc/uid/20000994-BAJHFBGH
In this case you do not have to release the string. You only release the Objects which you own (created through alloc/init, copy or retain). Go through the memory management doc by Apple. In this case, testArray owns the string. Hence it takes care of releasing it when no longer required
No need to release. You have to release only the objects that you have allocated.
Only if you also called [string retain]. Otherwise the memory is managed by NSArray. you might call [string retain] if you need to remove it from the array, but still keep a reference to it.
I use xcode 4.2 and this use ARC (Automatic Reference Counting).
This is not memory leak, because ARC send message of 'release':
NSNumber *xy = [[NSNumber alloc] init];
But it's possible to create memory leaks with this:
char *oldString = "Old String";
char newStrig = strdup(oldString);
I wanted to know that other types of memory leaks can be made?
(If is possible without using C or C++)
ARC only applies to Cocoa memory management. If you are casting between Cocoa and CoreFoundation for the toll-free bridge objects there are macros to transfer the memory-management.
You can leak memory in C, you can leak Core Foundation memory, and the static analyser helps with finding those.
ARC doesn't do away with memory management completely. It removes the need to manage memory for Cocoa objects and in some cases (because it can optimise away some retain release calls) is more efficient in managing memory, but you still need to understand memory management for Core Foundation objects, and for C memory.
You also need to understand Cocoa memory management to understand when to use strong, weak, or copy properties, and when to use Block_copy() and Block_release() on blocks, even though blocks are Cocoa objects and in most cases the correct memory management is handled for you with ARC.
Again; ARC doesn't do away with memory management. It simplifies it, and reduces the amount of code you have to write, but you still have to understand what is being done for you behind the scenes, and when you need to manage your own memory.
ARC can only work if you are using Objective-C memory allocations because its tied exclusively to that. In fact when you are using ARC the compiler does its best to match every alloc with an release (it cannot even guarantee that).
If you are using any other means than Objective-C allocations you are on your own again. ARC won't handle that.
do you need to release something very simple this?
NSString *a = #"Hello";
//[a release]; ?
I come from a Java/C# world, and am confused about when things should be released/retained.
No. You only need to release objects you init/alloc yourself or your instance variables in your class dealloc method.
No, you do not need to release a constant NSString, though it doesn't cause any problems if you do. Constant strings are special case of the memory management system. Since their content is known at compile time, it is statically defined in the application binary itself, so it never has to be allocated or freed at runtime. For that reason, its retain and release methods are noops.
This is only true for constant NSStrings (strings that start with #), and their toll free bridged cousin, constant CFStrings (defined using the CFSTR() macro).
Is there anyway to get int (or float) numbers into a NSString object without using alloc and a subsequent release?
int myInt = 25;
NSString *myString = [[NSString alloc] initWithFormat:#"%d",myInt];
...
[myString release];
EDIT:
Thanks for the answers, I should have been a little more clear in the question, I am particularly interested in using this on the iPhone. As #chuck stated I could use a convenience method, but I was under the impression that I should be avoiding these where possible on the iPhone for memory / performance reasons. I could be wrong though.
gary
There's no way to create an NSString without creating it at some point. But you could use a convenience constructor so you don't have the burden of ownership.
NSString *myString = [NSString stringWithFormat:#"%d", myInt];
It will still be created and destroyed (as everything must be), but you don't have to do it yourself.
I could use a convenience method, but I was under the impression that I should be avoiding these where possible on the iPhone for memory / performance reasons.
The “performance reason” is the cost of autoreleasing an object. This was, at one time, expensive on an iPhone. (I don't know whether it still is.) The only alternative is explicitly allocating it and releasing it yourself. As others have pointed out, you can't have an object without having allocated it, and you mustn't allocate it without releasing it. You need both things to happen one way or another.
The memory reason is simply that an autoreleased object lasts longer—specifically, until the autorelease comes due. Autorelease many objects, and your memory usage will pile up; pile it up high enough, and SpringBoard will tell your app to knock it off (and/or just kill it). The solution is to make the objects not last so long, which means either (1) creating and draining your own autorelease pool around a known batch of objects or (2) managing the objects' lifetimes (that is, allocating and releasing them) yourself.
This latter reason is not specific to the iPhone—it affects the Mac as well, although our ceiling is higher: Macs have more short-term memory, plus virtual memory, so we can get away with more memory usage. Even so, we Mac programmers should also try not to waste memory, partly because paging hell wrecks one's day, and partly because we will get email from users if our apps sit too high in the Activity Monitor list.
NSString *mystring = [NSString stringWithFormat:#"Hello: %d",myint];
it should be autoreleased if you create it this way
i think the convention is that unless you see the word init or alloc in the method name then it should return an autoreleased object. i.e. the object is added to the current autorelease pool and flushed when the app advances to next stage in lifecycle
You want
NSString *aStr=[[NSNumber numberWithInt:myInt] stringValue];
It returns an autoreleased string.
You could use an NSMutableString (-appendFormat:) or a standard C-string. However, fundamentally, no, you're going to have to allocate memory somewhere.
Why not define a macro... something like
#define intString(i1) [[[NSString alloc] initWithFormat:#"%d",i1] autorelease];
put it in your prefix header.
Most of the time autorelease will have zero impact on your app's overall memory usage. You only need to be concerned with autorelease if you're accumulating many object instances. For example:
for (int i = 0; i < 1000; ++i)
{
NSString* s = [NSString stringWithFormat:#"%d", i];
...
}
That example will accumulate at least 1000 different string instances before anything is released, which is not desirable. That's a situation where you would look for alternatives.
If you wanted to avoid creating a bunch of string instances you could use NSMutableString:
NSMutableString* s = [NSMutableString stringWithCapacity:20];
[s appendFormat:#"%d", 123];
...
[s setString:#""];
[s appendFormat:#"%d", 456];
...
It's questionable whether that's any faster than simply creating and releasing separate string instances, but that pattern may fit better with what you're trying to accomplish in your code.