Overriding dealloc


#1

Hi in this book they override dealloc.
So does it means that even though the dealloc is called upon to free the memory, but we have already override it. So instead of LITETALLY freeing the object from the memory we are calling NSLog to prove that dealloc actually happen so in this case it prints out sentences to prove that this method is called. SO ACTUALLY, the object is not really being deallocated because the method has been overwritten by NSLog in the .m file.Which means that the object still exist. So, class acts as a blueprint for object, so the method is already predefined in the class where dealloc would print out something instead of actually freeing out the object from the memoey.
Correct me if im wrong.


#2

An object is released regardless of whether or not the dealloc method has been overridden.

When an object is being deallocated, a dealloc message is sent to it, to give the object a chance to release any non-ARC resources it may have allocated. When the object receives this message, then it can release those resources or can simply print a message.

To see this process in action, build and run the following code.

//  main.m
//  Dealloc

#import <Foundation/Foundation.h>

// -------------------------------------------------------------------
//
@interface Bar: NSObject

@end

@interface FooBar: Bar

@property long bar;

@end

// -------------------------------------------------------------------
//
int main (int argc, const char * argv[])
{
    @autoreleasepool {
        FooBar *foo1 = [[FooBar alloc] init];
        FooBar *foo2 = [[FooBar alloc] init];
        foo1.bar = 2;
        foo2.bar = 3;
        NSLog (@"%s: %ld %ld", __PRETTY_FUNCTION__, foo1.bar, foo2.bar);
    }
    NSLog (@"%s: Bye...", __PRETTY_FUNCTION__);
    return 0;
}

// -------------------------------------------------------------------
//
@implementation FooBar

{
    char *buffer;
    unsigned long BSIZE;
    unsigned long index;
}

- (id)init
{
    NSLog (@"%s: allocating some non-ARC resource...", __PRETTY_FUNCTION__);
    self = [super init];
    if (self) {;
        BSIZE = 4 * 1024;
        index = 0;
        buffer = malloc (BSIZE); // non-ARC resource
    }
    return self;
}

- (void)dealloc
{
    NSLog (@"%s: releasing non-ARC resources...", __PRETTY_FUNCTION__);
    free (buffer);
}

@end

// -------------------------------------------------------------------
//
@implementation Bar

- (id)init
{
    NSLog (@"%s: nothing to allocate...", __PRETTY_FUNCTION__);
    self = [super init];
    return self;
}
- (void)dealloc
{
    NSLog (@"%s: nothing to release...", __PRETTY_FUNCTION__);
}

@end

#3

How can I relate this to what I have just learned about overriding methods?
In BMITime project, when the book override the -(float)bodyMassIndex method, the method only runs on what is written in the implementation file of the sub class as the sub class inherits the method.
But If I were to implement this concept into dealloc it does not work anymore.
Can you please explain this?


#4

I don’t quite understand the question, but perhaps do you mean that dealloc method is being called for both subclass and its superclass? If you are wondering about this, that’s because dealloc method is given special treatment by the memory-management system.


#5

My question is in BMITime project,I wanted to talk about 2 classes in this project, that is BNREmployee and BNRPerson.
BNREmployee is the subclass of BNRPerson.
We declared a method in BNRPerson.h file

in BNRPerson.m file we write this line of code

-(float)bodyMassIndex{ float h=[self heightInMeters]; return [self weightInKilos/(h*h)];}

Now the book says we override bodyMassIndex method in the subclass of BNRPerson which is BNREmployee

-(float)bodyMassIndex{ float normalBMI=[super bodyMassIndex]; return normalBMI*0.9;}

now if we run the project the result will execute the code written in the implementation file of the subclass with is BNREmployee as we already override the code in .m file of BNREmployee (BNREmployee is the subclass of BNRPerson, so it inherits BNRPerson’s method which is bodyMassIndex).

Ok when I’m applying this concept on overriding dealloc method. It just doesn’t fit because if I override dealloc method by writing the code in BNRAsset.m file like this

[code]
-(NSString *)description{
return [NSString stringWithFormat :@"<%@, $%u>", self.label, self.resaleValue];

-(void)dealloc{
NSLog(@“Deallocating %@”, self)}[/code]

And when I run the code above(the file that override dealloc method), the program LITERALLY deallocate the object like you said so instead of just replacing the process of LITERALLY deallocating the object.

But when i run the code of bodyMassIndex, the program runs the code written in the subclass where I override memory and execute the overwritten code.

If you still can understand, in BNRAsset.m file, we override the description method as shown above.
When we run the code(description method), instead of showing the memory location like default, the description method actually printed out according to the format of sentence that is written in the .m file of BNRAssets. More importantly it did not print our the memory address of the object.

Back to dealloc method.
If we override dealloc to print out a sentence like NSLog(@“Deallocating %@”, self);
Won’t it replace the original process of LITERALLY deallocating the object with the process of printing out the sentence “Deallocating (Something)”.

So, to sum up everything written up there. If I override a method. Won’t Xcode run the method that is overwritten?This situation contradict with overriding Dealloc method, even though I override the method, still like you say the object is still release and it also prints out sentence. But what I’m really expecting is the dealloc method to only print out sentence instead of actually freeing the object.
I hope you can understand what i’m saying here , sorry for my bad english


#6

dealloc method does not release the object. The object is released by the memory-management system; just before it releases the object, it calls the object’s dealloc method.

In your example, the dealloc method is doing exactly what you are expecting: it is only printing a log to the console; it is not freeing the object.


#7

ohh, so when we remove the object in the array like what you did in the book.
the object has already lost a pointer and its reference count is at 0.
So the memory management system still free the object, while dealloc method is also called.
So, what’s happening is that the object is freed by the memory management system right?


#8

Thank you ibex10 for your code example—I guess the issue is firstly it contains code or concepts not yet convered in the book and further it could possibly really benefit from more detailed commenting.

Would you consider adding comments please and or explanations of what is happening at each stage, it could help greatly.

Thanks in advance.

PS To clarify I too have been grasping the dealloc concept as raised on the book


#9

I am delighted to see that you are learning Objective-C, a language worth learning.

Instead of touching the old example code, I have created a new one.

The following example works with ARC only; you only need to release the non-ARC resources allocated.

//
//  main.m
//
//  Dealloc - How to use dealloc to release non-ARC resources allocated
//

#import <Foundation/Foundation.h>

// ------------------------------------------------------
//
@interface Foo: NSObject
- (instancetype) initWithString: (NSString *)str;
- (void) bar;
- (void) dealloc;
@end

// ------------------------------------------------------
//
@interface Bar: NSObject
- (instancetype) init;
- (void) dealloc;
@end

// ------------------------------------------------------
//
@implementation Foo
/* Two instance variables, not part of the interface */ {
    char * cstring;
    // First instance variable, a null terminated string.
    // since cstring is not an Objective-C object, it does __not__ participate in ARC;
    // we must manage the associated memory resource manually.
    
    Bar * bar;
    // Second instance variable.
    // since bar is an Objective-C object, it does participate in ARC;
    // associated memory will be automatically released by ARC.
}

- (instancetype) initWithString: (NSString *)str {
    NSLog (@"%s: %@...", __PRETTY_FUNCTION__, str);
    self = [super init];
    // copy the data, the UTF8String
    self->cstring = strdup ([str UTF8String]);
    // in copying the data, we have just allocated some memory
    // [see strdup () function in manual pages]
    // we are responsible for releasing the non-ARC memory allocated for the copy

    return self;
}

- (void) dealloc {
    NSLog (@"%s: release the non ARC resources allocated for: %s...", __PRETTY_FUNCTION__, cstring);
    // release the resource, just a block of memory in this case
    free (cstring);
}

- (void) bar {
    NSLog (@"%s: %s: create a Bar...", __PRETTY_FUNCTION__, cstring);
    bar = [Bar new];
}
@end

// ------------------------------------------------------
//
@implementation Bar
- (instancetype) init {
    NSLog (@"%s...", __PRETTY_FUNCTION__);
    self = [super init];
    return self;
}

- (void) dealloc {
    NSLog (@"%s: release non ARC resources, if any ", __PRETTY_FUNCTION__);
    // none
}
@end

// ------------------------------------------------------
//
int main (int argc, const char * argv[]) {
    @autoreleasepool {
        // create two objects of type Foo
        Foo * foo1 = [[Foo alloc] initWithString: @"jibber-1"];
        Foo * foo2 = [[Foo alloc] initWithString: @"jibber-2"];
        
        // do something with them...
        [foo1 bar];
        [foo2 bar];
        
        // ARC will release them here.
        // but just before doing that, it will send them each a dealloc message
        // to give them a chance to release any non-ARC resources allocated.
    }
    return 0;
}

In Xcode, paste the above example into a new Objective-C command line project to build and run it.

Let me know if anything is unclear.


#10

Thank you ibex10 ), I can come back if something isn’t understood.


#11

ibex10 I have been had an attempt at this though it seems clear that several references are beyond what we have been taught this far in the book.

  1. instancetype
  2. self = [super init]
  3. self->cstring
  4. strdup ([str UTF8String]);
  5. etc

Even having referenced these independently it was difficult patching it together.

Again thanks for the help, but ironically it seems I may need to read on further on order in order to understand your example


#12

Objective-C is a superset of the C Programming Language. One is expected to be very familiar with C before diving into Objective-C. :slight_smile:

This Apple document is worth reading: Programming with Objective-C.


#13

Thank you :grinning:

ps I am following through from the BNR Objective C book. So where as C has been introduced, these particular topics listed have not. Leaving something of a knowledge gap in regards to info needed for the task.