views:

92

answers:

2

Hi guys,

i got a problem,

if I run this code:

NSString *xml = [[NSString alloc] init];
xml=[NSString stringWithFormat:@"<%@>", @"msg"];
NSLog(@"%@\n",xml);
[xml release];

I got:
2010-09-07 11:45:15.523 test[1312:207] <msg>
2010-09-07 11:45:15.527 test[1312:207] *** -[CFString release]: message sent to deallocated instance 0x3d52ba0

I have red the memory guide and I think that: if i create an object using the alloc & init methods, I should release that object, but the rule does not play well here, why?

thanks

UPDATED

it seems that this line xml=[NSString stringWithFormat:@"<%@>", @"msg"]; is the problem. I replaced it by xml=@"something"; and it worked.

any idea why I can not use the stringWithFormat method here?

thanks again

UPDATED
Thanks for the answers @(Douwe Maan, BoltClock, Rod)

I have updated the code, just testing another way:

NSString *xml = [[NSString alloc] initWithFormat,@"<%@>", @"msg"];
NSLog(@"%@\n",xml);
[xml release];

interesting: if i run that code with the debug option enabled i get a message saying: *** -[CFString _cfTypeID]: message sent to deallocated instance 0x3954ab0

but if i run it without the debugging tool, it never sends a message saying that.

questions:
1. is it normal that the error message will not appear if i am not running the project with the debug tool?
2. so, what is the problem with initWithFormat?, is it the same that has stringWithFormat? (i think it does not create an autoreleased instance)
3. how may i know that some method returns an autoreleased instance?, is there some naming convention anywhere?

thanks!

A: 

You can use the stringWithFormat in your code. The correct code would be

NSString *xml=[NSString stringWithFormat:@"<%@>", @"msg"];
NSLog(@"%@\n",xml);

The message stringWithFormat allocates in the autorelease pool. It is thus released automatically. You are reusing the xml variable and "loosing" the pointer that was first allocated.

If you want to keep the value of xml around, for some reason, you might want to try

NSString *xml = [[NSString alloc] init];
NSString *newXml=[NSString stringWithFormat:@"<%@>", @"msg"];
NSLog(@"%@\n",newXml);
[xml release];
Rod
+2  A: 

Both @"some string" (apparently not, read @BoltClock's second comment) and [NSString stringWithFormat:@"some string with object: %@", someObject] return an autoreleased instance of NSString. You can use this object any way you like, but you don't own it (since you didn't alloc, copy or retain it), so you don't have to and shouldn't release it yourself.

Also, in your code, you actually have two NSString objects, the one you alloc'd (on line 1) and the one that is alloc'ed for you when you call stringWithFormat:, on line 2. On line 2 you're re-pointing the variable xml to the second NSString, but the first one is still around in memory, so you're creating a memory leak (as you haven't released it)! You didn't have to alloc this first one anyway, as your second NSString is the only one you're actually using.

So the correct code would be, getting rid of the release call and the first NSString:

NSString *xml = [NSString stringWithFormat:@"<%@>", @"msg"];
NSLog(@"%@\n", xml);

Questions:

  1. Hmm, I'm not sure why that error would occur in the first place...
  2. init... should be called after alloc'ing something, so it's always [[Object alloc] initWithSomething]. The autorelease-version of this is [Object objectWithSomething], which does essentially this: return [[[Object alloc] initWithSomething] autorelease].
  3. You don't really need to know what does and does not return an autoreleased object, just what you own, and should thus release, and do not own. You own everything you alloc, copy or retain, and you do not own everything else.
Douwe Maan
And to add to that, you should never use convenience methods on something you've already called `init` or `copy` on. It *will* cause a leak, and you *won't* get a chance to release that non-autoreleased object!
BoltClock
By the way, `@"some string"` is **not** an autoreleased object. It's a compile-time constant string object.
BoltClock
Wait, what do you mean by 'use convenience methods on something you've already called init or copy on'?
Douwe Maan
RE your second comment: Seriously? I didn't know that... Got a source for that? (Not that I don't believe you, I'd just like to read it somewhere myself ;) )
Douwe Maan
@DouweM: the `xml` variable will be changed to point to the object created using the convenience method (in this case `stringWithFormat:`). The `[[NSString alloc] init]` object will continue to exist in memory but is no longer accessible if nothing else in the program is pointing to it. So it can't be released and you get a leak. As for the compile-time constant string, see [this question](http://stackoverflow.com/questions/687962/do-i-need-to-release-nsstring-generated-using)
BoltClock
@BoltClock Ah yeah, I already edited my post on that first thing. Will read that post on `@"strings"`.
Douwe Maan
what about using `NSString *xml= [NSString alloc] initWithFormat:@"<%@>", @"msg"];` ???
jhon
Yup, you can do that too, but as you own the object that way, you have to make sure to release it later on too.
Douwe Maan
@Douwe Maan: Thanks for your answers
jhon
I have created another question about the latest problem i found, if you're interested, please visit : http://stackoverflow.com/questions/3670224/iphone-threads-release-pool-object-release-message-sent-to-deallocated
jhon