PDA

View Full Version : dealloc undeclared




jamesapp
Apr 17, 2008, 10:48 AM
james-collinss-macbook-pro:prog15 jamescollins$ gcc -framework Foundation AddressBook.m prog15.11.m -o prog15.11
AddressBook.m: In function ‘-[AddressBook initWithName:]’:
AddressBook.m:8: warning: conflicting types for ‘-(id)initWithName:(NSString *)name’
AddressBook.h:11: warning: previous declaration of ‘-(AddressBook *)initWithName:(NSString *)name’
AddressBook.m: In function ‘-[AddressBook list]’:
AddressBook.m:34: warning: ‘cString’ is deprecated (declared at /System/Library/Frameworks/Foundation.framework/Headers/NSString.h:345)
AddressBook.m:39: warning: ‘cString’ is deprecated (declared at /System/Library/Frameworks/Foundation.framework/Headers/NSString.h:345)
AddressBook.m:40: warning: ‘cString’ is deprecated (declared at /System/Library/Frameworks/Foundation.framework/Headers/NSString.h:345)
AddressBook.m:48: error: ‘dealloc’ undeclared (first use in this function)
AddressBook.m:48: error: (Each undeclared identifier is reported only once
AddressBook.m:48: error: for each function it appears in.)
AddressBook.m:48: error: syntax error before ‘{’ token
AddressBook.m: At top level:
AddressBook.m:53: warning: incomplete implementation of class ‘AddressBook’
AddressBook.m:53: warning: method definition for ‘-dealloc’ not found

got these error messages when i tried to compile a program from a book on Objective-C.

-i was told cString is no longer used, so i understand that warning message.
the thing that i don't understand is AddressBook.m:48 error: 'dealloc' undeclared (first use in this function)...
i have in my interface file

-(void) dealloc;


i will include the interface file which i called AddressBook.h

#import <Foundation/NSArray.h>
#import <stdio.h>
#import "AddressCard.h"

@interface AddressBook: NSObject
{
NSString *bookName;
NSMutableArray *book;
}

-(AddressBook *) initWithName: (NSString *) name;
-(void) addCard: (AddressCard *) theCard;
-(int) entries;
-(void) list;
-(void) dealloc;

@end


and my implementation file which i called AddressBook.m

#import "AddressBook.h"

@implementation AddressBook;

// set up the AddressBook's name and an empty book

-(id) initWithName: (NSString *) name
{
self = [super init];
if (self) {
bookName = [[NSString alloc] initWithString: name];
book = [[NSMutableArray alloc] init];
}

return self;
}

-(void) addCard: (AddressCard *) theCard
{
[book addObject: theCard];
}

-(int) entries
{
return [book count];
}

-(void) list
{
int i, elements;
AddressCard *theCard;

printf ("\n======== Contents of: %s =========\n",
[bookName cString]);
elements = [book count];

for ( i = 0; i < elements; ++i ) {
theCard = [book objectAtIndex: i];
printf ("%-20s %-32s\n", [[theCard name] cString],
[[theCard email] cString]);
}

printf("========================================\
============\n\n");


-(void) dealloc
{
[bookName release];
[book release];
[super dealloc];
}
@end


and my test file which i called prog15.11.m

#import "AddressBook.h"
#import <Foundation/NSAutoreleasePool.h>

int main (int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

NSString *aName = @"Julia Kochan";
NSString *aEmail = @"jewls337@axlc.com";
NSString *bName = @"Tony Iannino";
NSString *bEmail = @"tony.iannino@techfitness.com";
NSString *cName = @"Stephen Kochan";
NSString *cEmail = @"steve@kochan-wood.com";
NSString *dName = @"Jamie Baker";
NSString *dEmail = @"jbaker@kochan-wood.com";

AddressCard *card1 = [[AddressCard alloc] init];
AddressCard *card2 = [[AddressCard alloc] init];
AddressCard *card3 = [[AddressCard alloc] init];
AddressCard *card4 = [[AddressCard alloc] init];

AddressBook *myBook = [AddressBook alloc];

// first set up four address cards

[card1 setName: aName andEmail: aEmail];
[card2 setName: bName andEmail: bEmail];
[card3 setName: cName andEmail: cEmail];
[card4 setName: dName andEmail: dEmail];

// now initialize the address book

myBook = [myBook initWithName: @"Linda's Address Book"];

printf ("Entries in address book after creation: %i\n",
[myBook entries]);

// Add some cards to the address book

[myBook addCard: card1];
[myBook addCard: card2];
[myBook addCard: card3];
[myBook addCard: card4];

printf ("Entries in address book after adding cards: %i\n\n",
[myBook entries]);

// list all the entries in the book now

[myBook list];

[card1 release];
[card2 release];
[card3 release];
[card4 release];
[myBook release];
[pool release];
return 0;
}


didn't i declare dealloc in my interface file?
what is the syntax error before '{' token?



Nutter
Apr 17, 2008, 11:27 AM
You're only importing <Foundation/NSArray.h> in your header file. -(void)dealloc is declared <Foundation/NSObject.h>

I'd suggest that you change the import statement to the following:
#import <Foundation/Foundation.h>

This will include all the headers for the Foundation framework, including both NSObject.h and NSArray.h.

It isn't necessary to redeclare -(void)dealloc in your header file, as it's declared by the superclass, NSObject.

By the way, you can use -UTF8String instead of -cString.

Krevnik
Apr 17, 2008, 03:13 PM
Another game of spot the bug. :)

The bug is here, at the end of the list method:


-(void) list
{
int i, elements;
AddressCard *theCard;

printf ("\n======== Contents of: %s =========\n",
[bookName cString]);
elements = [book count];

for ( i = 0; i < elements; ++i ) {
theCard = [book objectAtIndex: i];
printf ("%-20s %-32s\n", [[theCard name] cString],
[[theCard email] cString]);
}

printf("========================================\
============\n\n");


-(void) dealloc
{
[bookName release];
[book release];
[super dealloc];
}


If you look closely, the list method isn't closed off. This leads to the series of compile errors you see. Fix that, and the dealloc undeclared error should go away too.

jamesapp
Apr 18, 2008, 12:22 PM
where should i close off list.
i tried at the end of

AddressCard *theCard;

got more error messages
i closed off list with '}', is that what you meant

kainjow
Apr 18, 2008, 12:26 PM
i closed off list with '}', is that what you meant

Yes, put the } right after your printf() function call and before the dealloc method.

jamesapp
Apr 18, 2008, 12:31 PM
tried to put '}' right after printf and before dealloc
got following error messages when i tried to compile

james-collinss-macbook-pro:prog15 jamescollins$ gcc -framework Foundation AddressBook.m prog15.11.m -o prog15.11
AddressBook.m: In function ‘-[AddressBook initWithName:]’:
AddressBook.m:8: warning: conflicting types for ‘-(id)initWithName:(NSString *)name’
AddressBook.h:11: warning: previous declaration of ‘-(AddressBook *)initWithName:(NSString *)name’
Undefined symbols:
".objc_class_name_AddressCard", referenced from:
literal-pointer@__OBJC@__cls_refs@AddressCard in ccBDrI05.o
ld: symbol(s) not found
collect2: ld returned 1 exit status

iSee
Apr 18, 2008, 12:49 PM
It actually compiled, so now you're on to other bugs!

Here's the one causing the first warning:

in the header, initWithName returns an AddressBook pointer, while in the .m file it returns an id:
Header:
-(AddressBook *) initWithName: (NSString *) name;
.m file:
-(id) initWithName: (NSString *) name

kainjow
Apr 18, 2008, 01:08 PM
Undefined symbols:
".objc_class_name_AddressCard", referenced from:
literal-pointer@__OBJC@__cls_refs@AddressCard in ccBDrI05.o
ld: symbol(s) not found
collect2: ld returned 1 exit status

Looks like you're not compiling AddressCard into your code. Try compiling like this:

gcc -framework Foundation AddressCard.m AddressBook.m prog15.11.m -o prog15.11

Eraserhead
Apr 18, 2008, 01:35 PM
You also should put if blocks around the stuff you're releasing i.e.


if(bookName!=nil){
[bookName release];
}
if(book!=nil){
[book release];
}

Krevnik
Apr 18, 2008, 03:50 PM
You also should put if blocks around the stuff you're releasing i.e.


if(bookName!=nil){
[bookName release];
}
if(book!=nil){
[book release];
}


I have been curious, how needed is that? In my experience, calling release on a nil object is usually safe(ish).

Cromulent
Apr 18, 2008, 04:11 PM
I have been curious, how needed is that? In my experience, calling release on a nil object is usually safe(ish).

You said it yourself. Safe(ish) is not safe :). Better be safe than sorry, I can imagine trying to debug a possible error relating from that to be rather stressful.

Krevnik
Apr 18, 2008, 04:26 PM
You said it yourself. Safe(ish) is not safe :). Better be safe than sorry, I can imagine trying to debug a possible error relating from that to be rather stressful.

Well, the main reason I say safe-ish, is that I haven't seen a crash from calling release on a nil object... But yeah, defensive is usually better. :P

iSee
Apr 18, 2008, 04:48 PM
It *is* safe to send messages to nil (including release).
It will do nothing. The return value will be nil.

http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Articles/chapter_2_section_3.html#//apple_ref/doc/uid/TP30001163-CH11-SW7

kainjow
Apr 18, 2008, 05:15 PM
On the other hand if you're dealing with CoreFoundation types, you must check for NULL before releasing those when using CFRelease().

GeeYouEye
Apr 18, 2008, 05:44 PM
Nope, releasing nil in dealloc isn't just safe-ish, it's desired. Apple does it throughout Cocoa that way. There's a huge discussion of this very topic on Apple's Cocoa-dev mailing list. Go right ahead and get rid of those if's.

Sbrocket
Apr 18, 2008, 09:18 PM
[nil release]; is a perfectly fine message to send, so the if blocks are unnecessary.

See http://www.cocoabuilder.com/archive/message/cocoa/2008/4/18/204503 if you'd like to read up on the reasons and history for it, its a pretty good thread.

Krevnik
Apr 19, 2008, 12:36 AM
Nope, releasing nil in dealloc isn't just safe-ish, it's desired. Apple does it throughout Cocoa that way. There's a huge discussion of this very topic on Apple's Cocoa-dev mailing list. Go right ahead and get rid of those if's.

Awesome, now I know all those [var release] lines in my older code weren't the result of some delusion. I was being productively lazy. :)

jamesapp
Apr 19, 2008, 08:51 AM
compiled with AddressCard.m and program compiled
still confused about
warning: conflicting types for ‘-(id)initWithName:(NSString *)name’
AddressBook.h:11: warning: previous declaration of ‘-(AddressBook *)initWithName:(NSString *)name’

kainjow
Apr 19, 2008, 09:45 AM
Reread iSee's post. You need to keep the method declaration and implementation the same. They are different.

jamesapp
Apr 19, 2008, 09:47 AM
thanks