Not seeing dealloc messages


#1

When I run the last exercise in chapter 19. The program seems to execute properly but I’m nit seeing the dealloc nslogs messages. I added a few lines at the end on main to check the employees array and I do see the count [employees count] go from 10 to 9 and then to 0 when employees is set to nil. But none of the expected dealloc messages. I have double checked my code and I’m pretty sure it matches the text in the book. Any suggestion to help me understand what I’m doing wrong?

Thanks, Stephen

Ps…: Excellant book so far!


#2

I suspect that your objects are not getting properly deallocated because they still have an owner. Take another look at your code and see if you can figure out why they aren’t getting deallocated.


#3

I am completely stumped. It all looks right. I even tried a for loop to remove objects from the employees array until it was empty. Still no dealloc messages.

////////////////////////////////////////////////////////////////////////////
//  Person.h
//  BMITime
//

#import <Foundation/Foundation.h>

@interface Person : NSObject
{
    float heightInMeters;
    int weightInKilos;
}

@property float heightInMeters;
@property int weightInKilos;

// Methods
- (float)bodyMassIndex;
@end

////////////////////////////////////////////////////////////////////////////
//  Person.m
//  BMITime
//

#import "Person.h"

@implementation Person

@synthesize heightInMeters, weightInKilos;

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

- (void)dealloc
{
    NSLog(@"deallocating %@", self);
}

@end

////////////////////////////////////////////////////////////////////////////
//  Employee.h
//  BMITime
//

#import "Person.h"
@class Asset;

@interface Employee : Person
{
    int employeeID;
    NSMutableArray *assets;
}
@property int employeeID;

- (void)addAssetObject:(Asset *)a;
- (unsigned int)valueOfAssets;

@end

////////////////////////////////////////////////////////////////////////////
//  Employee.m
//  BMITime
//

#import "Employee.h"
#import "Asset.h"

@implementation Employee

@synthesize employeeID;

- (void)addAssetObject:(Asset *)a
{
    // Is assets nil?
    if (!assets) {
        
        // Create the array
        assets = [[NSMutableArray alloc] init];
    }
    [assets addObject:a];
}

- (unsigned int)valueOfAssets
{
    // Sum up the resale value of the assets
    unsigned int sum = 0;
    for (Asset *a in assets) {
        sum += [a resaleValue];
    }
    return sum;
}

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

- (NSString *)description
{
    return [NSString stringWithFormat:@"<Employee %d: $%d in assets>",
            [self employeeID], [self valueOfAssets]];
}

- (void)dealloc
{
    NSLog(@"deallocating %@", self);
}

@end


////////////////////////////////////////////////////////////////////////////
//  Asset.h
//  BMITime
//

#import <Foundation/Foundation.h>

@interface Asset : NSObject
{
    NSString *label;
    unsigned int resaleValue;
}
@property (strong) NSString *label;
@property unsigned int resaleValue;

@end


////////////////////////////////////////////////////////////////////////////
//  Asset.m
//  BMITime
//

#import "Asset.h"

@implementation Asset

@synthesize label, resaleValue;

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

- (void)dealloc
{
    NSLog(@"deallocating %@", self);
}

@end

//////////////////////////////////////////////////////////////////////////
//
//  main.m
//  BMITime

#import <Foundation/Foundation.h>
#import "Employee.h"
#import "Asset.h"

int main (int argc, const char * argv[])
{

    @autoreleasepool {
        
        // Create an array of Employee objects
        NSMutableArray *employees = [[NSMutableArray alloc] init];
        
        for (int i = 0; i < 10; i++) {
            
            // Create an instance of Employee
            Employee *person = [[Employee alloc] init];
        
            // Give the instance variables interesting values
            [person setWeightInKilos:90 + i];
            [person setHeightInMeters:1.8 - i/10.0];
            [person setEmployeeID:i];
            
            // Put the employee in the employee array
            [employees addObject:person];
        }
        
        // Create 10 assets
        for (int i = 0; i < 10; i++) {
            
            // Create an asset
            Asset *asset = [[Asset alloc] init];
            
            // Give it an interesting label
            NSString *currentLabel = [NSString stringWithFormat:@"Laptop %d", i];
            [asset setLabel:currentLabel];
            [asset setResaleValue:i * 17];
            
            // Get random number between 0 and 9 inclusive
            NSUInteger randomIndex = random() % [employees count];
            
            // Find that employee
            Employee *randomEmployee = [employees objectAtIndex:randomIndex];
            
            // Assign the asset to the employee
            [randomEmployee addAssetObject:asset];
        }
        
        NSLog(@"Employees: %@", employees);
        
        //NSLog(@"object count: %lu", [employees count]);
        
        NSLog(@"giving up ownership of one employee");
        for (int i = 0; i < 10; i++) {
            
            [employees removeObjectAtIndex:0];
            
        }
            
        //NSLog(@"object count: %lu", [employees count]);
        
        NSLog(@"giving up ownership of array");
        
        employees = nil;
        
        //NSLog(@"object count: %lu", [employees count]);
        
    }
    return 0;
}


#4

Ok. So I have found that if I release person after adding person to the employees array,

// Put the employee in the employee array
[employees addObject:person];
[person release];

then when I remove objects from the array at the end main, I do get the dealloc messages from the employee class.

Setting employees = nil doesn’t seem to have an effect. But if I release employees,

NSLog(@"giving up ownership of array")
        [employees release];
        employees = nil;

then I see the dealloc message fire.

[quote]2011-10-28 05:52:34.025 BMITime[10193:707] Employees: (
"<Employee 0: $0 in assets>",
"<Employee 1: $153 in assets>",
"<Employee 2: $119 in assets>",
"<Employee 3: $68 in assets>",
"<Employee 4: $0 in assets>",
"<Employee 5: $136 in assets>",
"<Employee 6: $119 in assets>",
"<Employee 7: $34 in assets>",
"<Employee 8: $0 in assets>",
"<Employee 9: $136 in assets>"
)
2011-10-28 05:52:34.027 BMITime[10193:707] giving up ownership of one employee
2011-10-28 05:52:34.027 BMITime[10193:707] deallocating <Employee 0: $0 in assets>
2011-10-28 05:52:34.028 BMITime[10193:707] giving up ownership of array
2011-10-28 05:52:34.028 BMITime[10193:707] deallocating <Employee 1: $153 in assets>
2011-10-28 05:52:34.029 BMITime[10193:707] deallocating <Employee 2: $119 in assets>
2011-10-28 05:52:34.030 BMITime[10193:707] deallocating <Employee 3: $68 in assets>
2011-10-28 05:52:34.030 BMITime[10193:707] deallocating <Employee 4: $0 in assets>
2011-10-28 05:52:34.031 BMITime[10193:707] deallocating <Employee 5: $136 in assets>
2011-10-28 05:52:34.031 BMITime[10193:707] deallocating <Employee 6: $119 in assets>
2011-10-28 05:52:34.032 BMITime[10193:707] deallocating <Employee 7: $34 in assets>
2011-10-28 05:52:34.032 BMITime[10193:707] deallocating <Employee 8: $0 in assets>
2011-10-28 05:52:34.033 BMITime[10193:707] deallocating <Employee 9: $136 in assets>
Program ended with exit code: 0[/quote]

But I don’t ever see the asset dealloc messages. I have also tried to release the assets after adding them to the randomEmployee with no effect.

// Assign the asset to the employee [randomEmployee addAssetObject:asset]; [asset release];


#5

Hmm. It looks like you are not using ARC.

When you created the project, did you check the box that said “Use Automatic Reference Counting”? Is “Objective-C Automatic Reference Counting” set to “Yes” in the build settings?


#6

Wow… That fixed it!

As soon as I built the project after setting ARC to yes, all of the release messages were flagged as errors. I removed them, recompiled and it ran as expected.
Lesson Learned!
That’s for the help.

[quote]2011-10-29 08:06:03.831 BMITime[61727:707] Employees: (
"<Employee 0: $0 in assets>",
"<Employee 1: $153 in assets>",
"<Employee 2: $119 in assets>",
"<Employee 3: $68 in assets>",
"<Employee 4: $0 in assets>",
"<Employee 5: $136 in assets>",
"<Employee 6: $119 in assets>",
"<Employee 7: $34 in assets>",
"<Employee 8: $0 in assets>",
"<Employee 9: $136 in assets>"
)
2011-10-29 08:06:03.833 BMITime[61727:707] giving up ownership of one employee
2011-10-29 08:06:03.834 BMITime[61727:707] deallocating <Employee 0: $0 in assets>
2011-10-29 08:06:03.835 BMITime[61727:707] deallocating <Employee 0: $0 in assets>
2011-10-29 08:06:03.835 BMITime[61727:707] giving up ownership of array
2011-10-29 08:06:03.835 BMITime[61727:707] deallocating <Employee 1: $153 in assets>
2011-10-29 08:06:03.836 BMITime[61727:707] deallocating <Employee 1: $153 in assets>
2011-10-29 08:06:03.837 BMITime[61727:707] deallocating asset: <Laptop 9: $153 >
2011-10-29 08:06:03.837 BMITime[61727:707] deallocating <Employee 2: $119 in assets>
2011-10-29 08:06:03.838 BMITime[61727:707] deallocating <Employee 2: $119 in assets>
2011-10-29 08:06:03.838 BMITime[61727:707] deallocating asset: <Laptop 7: $119 >
2011-10-29 08:06:03.839 BMITime[61727:707] deallocating <Employee 3: $68 in assets>
2011-10-29 08:06:03.839 BMITime[61727:707] deallocating <Employee 3: $68 in assets>
2011-10-29 08:06:03.840 BMITime[61727:707] deallocating asset: <Laptop 0: $0 >
2011-10-29 08:06:03.840 BMITime[61727:707] deallocating asset: <Laptop 4: $68 >
2011-10-29 08:06:03.841 BMITime[61727:707] deallocating <Employee 4: $0 in assets>
2011-10-29 08:06:03.841 BMITime[61727:707] deallocating <Employee 4: $0 in assets>
2011-10-29 08:06:03.842 BMITime[61727:707] deallocating <Employee 5: $136 in assets>
2011-10-29 08:06:03.842 BMITime[61727:707] deallocating <Employee 5: $136 in assets>
2011-10-29 08:06:03.843 BMITime[61727:707] deallocating asset: <Laptop 3: $51 >
2011-10-29 08:06:03.843 BMITime[61727:707] deallocating asset: <Laptop 5: $85 >
2011-10-29 08:06:03.844 BMITime[61727:707] deallocating <Employee 6: $119 in assets>
2011-10-29 08:06:03.844 BMITime[61727:707] deallocating <Employee 6: $119 in assets>
2011-10-29 08:06:03.845 BMITime[61727:707] deallocating asset: <Laptop 1: $17 >
2011-10-29 08:06:03.845 BMITime[61727:707] deallocating asset: <Laptop 6: $102 >
2011-10-29 08:06:03.846 BMITime[61727:707] deallocating <Employee 7: $34 in assets>
2011-10-29 08:06:03.847 BMITime[61727:707] deallocating <Employee 7: $34 in assets>
2011-10-29 08:06:03.847 BMITime[61727:707] deallocating asset: <Laptop 2: $34 >
2011-10-29 08:06:03.848 BMITime[61727:707] deallocating <Employee 8: $0 in assets>
2011-10-29 08:06:03.848 BMITime[61727:707] deallocating <Employee 8: $0 in assets>
2011-10-29 08:06:03.849 BMITime[61727:707] deallocating <Employee 9: $136 in assets>
2011-10-29 08:06:03.849 BMITime[61727:707] deallocating <Employee 9: $136 in assets>
2011-10-29 08:06:03.850 BMITime[61727:707] deallocating asset: <Laptop 8: $136 >
[/quote]


#7

Incidentally, I didn’t initially set my project for ARC, if you have done the same, you can go to …

Edit | Refactor | Convert to Objective-C ARC


#8

Ditto. I had been using Xcode 4.1 and changed to 4.2 and failed to turn the ARC on. Now its working like a charm. Thank you!


#9

I am having exactly the same problem, and when I checked the build settings, sure enough ARC was set to no. So I changed to yes, thinking all would be fixed, but no. Specifically, the build failed. I also tried using the Edit|Refactor menu, but the ARC option is greyed out. Now I’m completely stumped. Any thoughts or hints? I’m using 4.2 if that’s useful to know.


#10

I recall seeing in the release notes for Xcode 4.2.1 a reference to ARC conversions not working properly in some cases under 4.2. You might upgrade to 4.2.1 and/or start over.


#11

I’ve just upgraded to OSX Lion, and installed XCode 4.2.1, but I created this project before I did this.
How do I change the build settings to use Objective-C Automatic Reference Counting for this project?
Or do I have to create a new project that uses ARC and start all over - I can’t find how to change the build settings…

Waggers


#12

I am using XCode 4.2 on OSX 10.6.8 and I don’t see dealloc either. When I go to the build settings I do not see and option for ARC. Is it available with this configuration? Can someone tell me specifically where to find it? Thanks!

Edit: Please disregard this question, I just found it. Sorry


#13

Could you tell me how you found the build settings, tmadden.

Or someone.

Please!!! :slight_smile:


#14

At the top left of the outline view, you’ll see the blueprint-paper icon, that says the name of the project and something like “1 target, Mac OS X SDK 10.7”. Select that. Under “TARGETS”, select the target (which is the name of your project). then, under the “Build Settings” tab, you’ll see an outline view. Under “Apple LLVM Compiler - 3.0 Language”. Set “Objective-C Automatic Reference Counting” to “Yes”.


#15

Thanks Aaron, took a while to find cos you need to select “All” under “Build Settings”, not just “Basic” - but that works now, and a useful exercise investigating how Xcode works.

waggers


#16

Running Snow Leopard, XCode 4.2, problems with the ARC. Followed Aaron’s steps on the compiler settings.
XCode error:
ld: file not found: /Developer/usr/lib/arc/libarclite_macosx.a
Command /Developer/usr/bin/clang failed with exit code 1

According to Stephen Kochan
"ARC is not supported for Mac OS X apps running under Snow Leopard (but it does support iOS apps)."

classroomm.com/objective-c/index … ic=5763.15

If true, would be great to alert readers of your book that Lion is required. If not true, please help! Thanks!

dbomberg


#17

I have Snow Leopard and XCode 4.2 - and I guess I cannot use ARC. So I saw this post, and learnt to release the “employees”. And in Employees.m - I did the same thing for Assets - set it to release, and made it nil. Then I started getting al the dealloc messages… thanks to sdw1361 :smiley:


#18

I’m having the same problem, with not showing the dealloc NSLog messages. However I can’t tell if I have ARC on or off. I’ve googled every way I can think of phrasing “how to tell if ARC is on” and I can’t find a solution. I searched through the Project build settings and don’t see anything about ARC. I considered upgrading to Xcode 4.2.1 as suggested in this thread, but that requires OS X Lion which is more hassle than I want to go through at the moment to finish this chapter.

I tried converting to ARC with Edit -> Refactor -> Convert to Objective-C ARC but it’s greyed out.

Finally I decided to create a new project so I could make sure I enabled ARC, but when I did so, there is nothing for me to check or any way to say that I want ARC on. Is this because I’m creating a command-line tool for OSX instead of an iOS application? I’m using XCode 4.2 on Snow Leopard OS X 10.6.8

I’m really stuck on this, any help would be appreciated

thanks

** UPDATE **

Sorry, after reading the link two posts up I realized that ARC is not supported on Snow Leopard with OS X apps - only iOS apps. So anyone else that happens to be doing Chapter 19 of this book needs to be running Lion in order to see the final example program output properly. This fact would make an excellent sticky for this section of the Forum


#19

I have had the same problem, but on one of the machines we develop on ARC is not supported. That machine is a 32-bit MacBookPro running Snow Leopard. ARC is only supported on 64-bit machines. The refactoring to ARC is greyed out and if you turn ARC on through Apple LLVM Compiler 3.0 settings, an error occurs “-fobjc-arc is not supported with fragile abi”.
My son is using the 64-bit MacPro and when I build the project with ARC on that machine it works fine. I think it is time we switch machines… :slight_smile:


#20

I’m using snow leopard, so I can’t use ARC for command line projects. I’m try to manually implement the object release (autorelease).What I have here, partially works.
I put the “autorelease” behind the inits of the “employees” array, and the “person” instance. It allows the deallocation to display in the console. but it’s not exactly correct. I also put an autorelease in the Assets class, behind the NSString declaration in the description method(not shown here)

[code]NSMutableArray *employees = [[[NSMutableArray alloc]init]autorelease];
for (int i = 0; i < 10; i++) {
// Create an instance of Employee
Employee * person = [[[Employee alloc]init]autorelease];

        // give the person interesting values
        [person setWeightInKilos:34 +i];
        [person setHeightInMeters:1.4 - i/10.0];
        [person setEmployeeID:i];
        
        [employees addObject:person];
        
               }
    // create 10 assests
    for (int i = 0; i < 10; i++) {
        // Create an asset
        Asset *asset = [[Asset alloc]init];
        //Give the asset an interesting label
        NSString * currentLabel = [NSString stringWithFormat:@"Laptop %d",i];
        [asset setLabel:currentLabel];
        [asset setResaleValue:i* 17];

[/code]

partial from my console, the third line should be second.

I have iOS programming TBNR and I’m reading chapter 3, memory management. But that is all obsolete now right? I guess the answer is, I should upgrade to Lion.