Object existing after release - objective-c

Can anyone explain to me why class object still exist after release. Here is the code
#import <Foundation/Foundation.h>
#import "MyClass.h"
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
MyClass *class = [[MyClass alloc] init];
NSLog(#"%#", [class showMouse]);
NSLog(#"%#", [class printKbd]);
[class release];
NSLog(#"%#", [class printKbd]);
//still exist
[pool drain];
return 0;
}

Actually, dealloc does get called, you can check it by adding NSLog(#"dealloc called") inside dealloc method of MyClass.
Why does it still work then? When an object gets released, the memory is not zeroed, it's simply marked as free to use by system. As a result, the code may still exist at the address of the pointer and *class is simply a pointer to a block of memory. Here's the great SO answer that explains it in details.
Important thing to note is, should the program execution last any longer, the call to [class printKbd] would most likely crash. That's why it's important to assign nil to pointer, just to make sure we won't access the undefined part of memory.

Related

debugging objective c memory leak with xCode Leaks

I'm doing my first steps in finding memory leaks in xCode 4.5 and using the Leaks instrument. I found a couple of issues and seemed to fix them, but this one eludes me.
Here is the code:
RUBEImageInfo* imgInfo = [[[RUBEImageInfo alloc] init] autorelease];
NSString *nm = [NSString stringWithUTF8String:img->name.c_str()];
imgInfo->name = nm;
[imgInfo->name retain]; // I'm using it outside of this method
Leaks reports a leak in the second line, with the percentage next to the "i" at %100.
So I tried two things:
One, I marked nm with autohrleas like this:
NSString *nm = [[NSString stringWithUTF8String:img->name.c_str()] autorelease];
Two, I also tried calling release on nm after it's assignment to imgInfo->name so the code looks like this:
imgInfo->name = nm;
[imgInfo->name retain];
[nm release];
But in both cases the app crashes with BAD_ACCESS when I run it, and call [imgInfo->name UTF8String].
What am I missing?
EDIT following Rob's answer:
This is the RUBEImageInfo class:
#import "cocos2d.h"
#interface RUBEImageInfo : NSObject {
#public CCSprite* sprite; // the image
#public NSString* name; // the file the image was loaded from
#public class b2Body* body; // the body this image is attached to (can be NULL)
#public float scale; // a scale of 1 means the image is 1 physics unit high
#public float angle; // 'local angle' - relative to the angle of the body
#public CGPoint center; // 'local center' - relative to the position of the body
#public float opacity; // 0 - 1
#public bool flip; // horizontal flip
#public int colorTint[4]; // 0 - 255 RGBA values
}
#end
And the .m:
#import "RUBEImageInfo.h"
#implementation RUBEImageInfo
// Nothing much to see here. Just make sure the body starts as NULL.
-(id)init
{
if( (self=[super init])) {
body = NULL;
}
return self;
}
-(void) dealloc {
[name release];
[super dealloc];
}
#end
A couple of reactions:
Instruments identified where the leaked object was allocated, but in this case, this code might not be the source of the leak. You should:
ensure you release the name in the dealloc method of RUBEImageInfo; and
also, if you're setting name a second time, make sure you release the previous name object before you set it to a new object.
Your life will be much easier if you use declared properties rather than dereferencing class instance variables. For example, if name was declared as:
#property (nonatomic, copy) NSString *name; // you could use `retain`, too, but `copy` is safer when dealing with strings
Then you would set the name property as so:
RUBEImageInfo* imgInfo = [[[RUBEImageInfo alloc] init] autorelease];
NSString *nm = [NSString stringWithUTF8String:img->name.c_str()];
imgInfo.name = nm;
// this is no longer needed as the `name` setter will take care of memory semantics
// [imgInfo->name retain]; // I'm using it outside of this method
By using the setter accessor method (i.e. the "dot syntax" of imgInfo.name), it will take care of a lot of routine memory semantics of releasing any previous object that name may have referenced, and it will do the necessary copy or retain. Obviously, the RUBEImageInfo method dealloc still needs to release name, but at least it simplifies the memory semantics of the name property of RUBEImageInfo objects.
Since you are using manual reference counting, I'd encourage you to investigate the "static analyzer" (invoked by selecting "Analyze" from Xcode's "Product" menu). The Leaks tool in Instruments will tell you what leaked, but it doesn't tell you where the leak happened; it has no way of knowing; it can only show you where the leaked object was allocated and you'll have to hunt down the logic error yourself. The static analyzer can sometimes point out errors that lead to leaks, but more importantly, show you where the leak was caused, rather than just where the leaked object was originally instantiated. You should have a clean bill of health from the static analyzer before you even bother running Instruments.
Looking at your code sample, if you're not going to use declared properties (not sure why you wouldn't, as it makes life easier, but to each his own), I'd suggest making sure you initialize all of your objects in init and release all of them in dealloc:
#implementation RUBEImageInfo
-(id)init
{
if ((self=[super init])) {
body = NULL;
name = nil;
sprite = nil;
// I might initialize other class instance variables here, too, but that's up to you
}
return self;
}
-(void) dealloc {
[name release];
// shouldn't you release `body` and `sprite`, too?
[super dealloc];
}
#end
Then your code that sets the name instance variable would make sure to release the previous object before setting the new object. Thus the initial instantiation might look like:
RUBEImageInfo* imgInfo = [[[RUBEImageInfo alloc] init] autorelease];
NSString *nm = [NSString stringWithUTF8String:img->name.c_str()];
imgInfo->name = [nm retain]; // retain the new object
But if you update it later, you should:
NSString *nm = [NSString stringWithUTF8String:someNewImg->name.c_str()];
[imageInfo->name release]; // release the old one
imgInfo->name = [nm retain]; // retain the new object

Why aren't objects released when referencing them using __weak outside of an autorelease pool? [duplicate]

This question already has answers here:
Why isn’t my weak reference cleared right after the strong ones are gone?
(4 answers)
Closed 9 years ago.
In the following code, which is ARC'd and running 64-bit on Mac OS X 10.8.4, why is the instance of MyObj not being deallocated before the program terminates?
#import <Foundation/Foundation.h>
#interface MyObj : NSObject
#end
#implementation MyObj
- (void)dealloc
{
NSLog(#"MyObj dealloc'd %p", self);
}
#end
int main(int argc, const char * argv[])
{
MyObj* obj1 = [[MyObj alloc] init];
__weak MyObj* weakObj1 = obj1;
NSLog(#"Use it: %p\n", weakObj1);
// Why isn't MyObj deallocated here?
return 0;
}
__weak relies on the Objective-C runtime function objc_loadWeak. From Objective-C Automatic Reference Counting in the documentation for Clang 3.4:
id objc_loadWeak(id *object);
Precondition: object is a valid pointer which either contains a null
pointer or has been registered as a __weak object.
If object is registered as a __weak object, and the last value stored
into object has not yet been deallocated or begun deallocation,
retains and autoreleases that value and returns it. Otherwise returns
null. Equivalent to the following code:
id objc_loadWeak(id *object) {
return objc_autorelease(objc_loadWeakRetained(object));
}
Must be atomic with respect to calls to objc_storeWeak on object.
Rationale
Loading weak references would be inherently prone to race
conditions without the retain.
Since objc_loadWeak requires an autorelease pool, then you must have an autorelease pool present when using __weak. The pool can created by either NSAutoreleasePool or #autoreleasepool. If an autorelease pool is not present, then nothing will release your object after objc_loadWeak retains it and your object will therefore never be deallocated.
Here is a fix for the code above:
#import <Foundation/Foundation.h>
#interface MyObj : NSObject
#end
#implementation MyObj
- (void)dealloc
{
NSLog(#"MyObj dealloc'd %p", self);
}
#end
int main(int argc, const char * argv[])
{
#autoreleasepool {
MyObj* obj1 = [[MyObj alloc] init];
__weak MyObj* weakObj1 = obj1;
NSLog(#"Use it: %p\n", weakObj1);
// Now MyObj is deallocated
}
return 0;
}
weakObj1 is not going to be deallocated until main ends. When you are using ARC, which is what you should do, variables and objects won't be deallocated until the block where they were declared in ends. When this happens, all the objects that are not being strong referenced by any object will be deallocated.
Keep on mind that to deallocate an object a release message has to be sent to it. If you are using manual retain-release, MRR, you have to do it by yourself, if you are using automatic reference counting, ARC, the system will do it for you.

Array Via Setter?

This is just a test to help me learn Objective-C, it uses NSMutableArray to add tire objects to an instance variable in a car object:
// INTERFACE
#interface CarBody : NSObject {
NSMutableArray *tires;
}
// Should this be (id *) it works but I was convinced it would be pointer?
- (void) addTire:(id)newTire;
#end
#interface TireSnow : NSObject {
}
#end
// IMPLEMENTATION
#implementation CarBody
- (void) addTire:(id)newTire {
[tires addObject:newTire];
// ** Release here or in main()?
}
- (id) init {
[super init];
tires = [[NSMutableArray alloc] init];
NSLog(#"_init: %#", NSStringFromClass([self class]));
return self;
}
- (void) dealloc {
NSLog(#"_deal: %#", NSStringFromClass([self class]));
[tires release];
[super dealloc];
}
#end
I do have a few questions ...
In the addTire method, is the (id) right, I thought it was going to be (id *)
Releasing the item I am adding to the array, should I do it inside the setter or in main() after I call it?
Am I allocating / releasing the NSMutableArray (tires) in the right place, it feels right?
Is there a way to do this with NSArray (as I only want 4 tires), I did try this but got mixed up trying to alloc the array and define its size.
thanks in advance for any help ...
gary
EDIT:
I am reading the memory management rules, but they do take some time to absorb and do require a certain level of understanding that is difficult to gain when starting out. What I am wondering about in this situation is where would I release the newSnowTire that I alloc in main. When I add it to the array in the setter does that create a new object in the array (thats my understanding) so my thinking was that I would need to release the instance I got from alloc?
// MAIN
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
CarBody *newCarBody_001;
TireSnow *newSnowTire_001;
newCarBody_001 = [[CarBody alloc] init];
newSnowTire_001 = [[TireSnow alloc] init];
[newCarBody_001 addTire:newSnowTire_001];
// Clean up
[newCarBody_001 release];
[newSnowTire_001 release];
[pool drain];
return 0;
}
EDIT_002:
Just added the code to generate all 4 tires with the tire release moved into the loop after the setter is called.
// CREATE TIRES
for(int loopCounter=0; loopCounter<4; loopCounter++) {
newSnowTire_001 = [[TireSnow alloc] init];
[newCarBody_001 addTire:newSnowTire_001];
[newSnowTire_001 release];
}
I just checked this and it is correct ...
NewSnowTire_001 (alloc) RetainCount = 1
NewSnowTire_001 (addTire) RetainCount = 2
NewSnowTire_001 (release) RetainCount = 1
NewSnowTire_001 Finally Released by dealloc method.
(id) or (TireSnow*) is similar, I had problems with understanding this in the beginning too. So basically an object is of a pointer type (kind of), but the id is already a pointer, so you don't need a * after it.
In main. Releasing should happen in the same place as the alloc/retain/copy.
Seems okay to me.
You can use [[NSMutableArray alloc] initWithCapacity:4]. This is only a hint to the array, it will automatically expand if you insert more items. Check [tires length] in the addTire method.
Your -init should look more like this:
-(id)init
{
if (self = [super init]) {
// init here
}
return self;
}
This allows self to be nil if something breaks in the init-chain.
You should use id (not id*). Objective-C do not have a concept of a root object as you have in for example Java, where java.lang.Object is the root class for any and all classes. Cocoa adds two root classes (classes without a super class) named NSObject, and less common NSProxy. id is a pointer to any object regardless of super class.
It is unfortunate that id, and also Class, are defined as a pointers, which means they are the only places where you should not add the '*' character when defining references. An unfortunate legacy from the old days.
Release in main, you should always release objects int he same scope that you create or retain them. The addTire: method is exceptionally god example of this, never release objects that has been handed to you as an argument. Only release objects handed to you as a result (And even then only from the alloc, new and copy method).
The allocation and release of the instance variable tires is a schoolbook example of where it should be done. I would expand the init to check for the super class result, as this though (Never trust super to always work, or even return the same instance):
- (id) init {
self = [super init];
if (self) {
tires = [[NSMutableArray alloc] init];
NSLog(#"_init: %#", NSStringFromClass([self class]));
}
return self;
}
You can use NSArray if you have access to all four tires from the start. Best way would probably be to require the tires in the init method. If that is not a possibility then you have nothing to gain from using an NSArray over a NSMutableArray.
The type id is defined like this (in objc.h):
typedef struct objc_object {
Class isa;
} *id;
So id is already a pointer to an object. An id* would be a pointer to a pointer.
As for where you should release the tire — there's nothing in the code you posted that shows a need to release it at all. That object never claims ownership of the tire, so it has no need to release it. If something claimed ownership of the tire somewhere else in your code, then that object has a responsibility to release its claim when it's finished.
This is explained in the Objective-C memory management rules. It's pretty short and a must-read.

Allocation of instance variables?

Can anyone tell me if the NSString instance variable "planetName" needs to be allocated / released by me (as in the example below) or is that done when the class instance is created / allocated?
My understanding is that int and float don't need to be, but not sure about NSString & NSArray ...
#interface PlanetClass : NSObject {
NSString *planetName;
}
- (NSString *)planetName;
- (void)setPlanetName:(NSString *)value;
#end
Like this ...
- (id) init {
[super init];
planetName = [[NSString alloc] init];
return self;
}
- (void) dealloc {
[planetName release];
[super dealloc];
}
** ---------------------------------- **
EDIT: EDIT: Here is another version
** ---------------------------------- **
int main(int argc, const char *argv[]) {
// ** Allocated here
PlanetClass *newPlanet_01 = [[PlanetClass alloc] init];
NSString *newPlanetName = [NSString alloc] init];
// ** Set the instance variable pointer here
newPlanetName = #"Jupiter";
[newPlanet_01 setPlanetName:newPlanetName];
// ** Released here
[newPlanet_01 release];
return 0;
}
the init & dealloc methods would then be like this ...
- (id) init {
[super init];
return self;
}
- (void) dealloc {
// Always release the current copy of planetName
// pointed to by the class instance.
[planetName release]
[super dealloc];
}
The setPlanetName method would look like this ...
- (void)setPlanetName:(NSString *)newPlanetName {
if (planetName != newPlanetName) {
[planetName release];
planetName = [newPlanetName copy];
}
}
PS: I am not using properties or synthesize, I have not gotten that far yet.
cheers -gary-
Your code is valid, but there's probably no reason to initialize planetName to an empty string. One of the nice features of Objective-C is that you can send messages to a nil object with no consequence. If your class is initialized and you never call -setPlanetName:, planetName will be nil (instance variables are always initialized to nil), so when your -dealloc method calls [planetName release], nothing will happen.
In general, the best practice is to use -copy when setting an NSString instance variable, and -retain when setting most other objects as instance variables. As such, your -setPlanetName: method would look something like this:
- (void)setPlanetName:(NSString *)newPlanetName {
NSString *tempPlanetName = [newPlanetName copy];
[planetName release];
planetName = tempPlanetName;
}
You still have an issue with your new code.
In your main function, you release newPlanetName but this is a little wrong. Your PlanetClass retained it with its setPlanetName: method, but your PlanetClass never releases it again unless the name of the planet changes. It should not be up to the caller of setPlanetName: to keep hold of the string, it is your classes responsibility to deal with it appropriately.
Your old dealloc method is correct. It should release the planet's name because your PlanetClass no longer needs it. Your main method should not release the planet's name because the string returned by stringWithString: does not belong to you, and you give it to PlanetClass to take care of.
So, keep your old dealloc method, and remove the [newPlanetName release] from the main function and you should be alright from there.
As a shortcut, you can even call [newPlanet_01 setPlanetName:#"Jupiter"] and do away with the newPlanetName variable altogether in your main function.
planetName is a pointer which, like an int or float, does not need to be allocated or initialized.
Just like you can assign values to an int or float, you can point planetName at different instances of a string, or it can point at nothing.
When you init your class, planetName will be nil (not pointing at anything). If you point planetName to an instance of a string, you have to retain that string, and release in dealloc.
In other words, this:
planetName = [[NSString alloc] init];
is unnecessary and meaningless.
In your setPlanetName method you would need to release the existing string that planetName is pointing to, assign planetName to the new string, and then retain the new string.
Your dealloc method is correct.
Your code looks good. NSObject subclasses (NSString included) need to have their memory mananged by the object that owns them. In this case, that owner is PlanetClass.

Objective C Memory Management Confusion

I was reading the apple documentation for memory management, and came across something that I just don't understand. Basically, I don't understand why one does not need need to retain an instance variable through the "getter" method. I wrote this little program to see what would happen. I thought there would be a crash, but I am obviously missing something.
// main.m
// Test
//
#import <Foundation/Foundation.h>
#import "Test.h"
int main(int argc, char *argv[])
{
NSAutoreleasePool *p = [[NSAutoreleasePool alloc] init];
//Initialize the test object
Test *t = [[Test alloc] init];
//Set the value to 5
[t setMyNum:[NSNumber numberWithInt:5]];
//Save a temp number that points to the original number
NSNumber *tempNum = [t myNum];
//release old number and retain new
[t setMyNum:[NSNumber numberWithInt:7]];
//Shouldn't this crash because tempNum is pointing to a deallocated NSNumber???
NSLog(#"the number is %#",tempNum);
[p drain];
return 0;
}
Doesn't tempNum point to a deallocated object??
All help is appreciated.
EDIT
This is the code in the getter and setter methods
#import "Test.h"
#implementation Test
- (void)setMyNum:(NSNumber *)newNum {
[newNum retain];
[myNum release];
myNum = newNum;
}
-(NSNumber *)myNum {
return myNum;
}
#end
As you can see I am calling release on the old object.
EDIT
It was suggested, and I thought rightfully so that the reason the tempNum is still around is because it hadn't been autoreleased from the pool yet. But even after moving the [pool drain] to right before the NSLog message, there is not crash??? Weird.
Since you are not explicitly releasing any objects, nothing is being deallocated until the autorelease pool is allowed to drain. Try inserting [p drain] before the last NSLog call. It should crash the NSLog call.
Additionally, if you are not retaining the NSNumber in your setMyNum: method, you will find that it will crash if you add [p drain] before tempNum is assigned.
To clarify the original question, calling a getter method doesn't (and shouldn't) necessarily imply that the caller wants to take ownership (i.e. retain) the variable. If that was the case, this code would leak:
NSLog("Number is %#", [t myNum]);
Also, it appears that NSNumber has an optimization whereby for small numbers, they cache the NSNumber objects, retain an extra copy, and return that version. So for small constants, [NSNumber numberWithInt: N] will return an object with 2 reference counts (available via [theNumber retainCount]). To explicitly see what happens, use a larger constant in the program, an NSNumber will retain a 'fresh' object with a reference count of 1 (that will also be autoreleased).
#import "Test.h"
#implementation Test
- (void)setMyNum:(NSNumber *)newNum
{
[newNum retain];
[myNum release];
myNum = newNum;
}
-(NSNumber *)myNum
{
return myNum;
}
#end
Here in the setter method [myNum release] which releases the mynum, but then we are again giving some new value that is newnum, hence from the getter method the temporary number gets the number which has not been deallocated till the [p drain] so there will not be any crash.
#import "Test.h"
#implementation Test
(void)setMyNum:(NSNumber *)newNum
{
[newNum retain];
[myNum release];
myNum = newNum;
}
(NSNumber *)myNum
{
return myNum;
}
#end
Here is the setter method [myNum release]; Which releases the myNum, but then we are again giving some new value that is newNum, hence from the getter method the temporary number gets the number which has not been deallocated till the [p drain]; so there will not be any crash. Even if the following code will not crash as there is autorelease pool but no autorelease method.
[t setMyNum:[NSNumber numberWithInt:70]];
So releasing the pool will not deallocate the number.