1

i have the following code in a .h

@property (nonatomic, copy) NSString *username;

Then, username is assigned in this way when the user enter text in a TextField:

self.username = textField.text;

And then, in dealloc method i call release:

NSLog(@"%d",[username retainCount]);
[username release];
NSLog(@"%d",[username retainCount]);

But in the console it prints:

2011-01-11 23:09:52.468 IApp[2527:307] 1
2011-01-11 23:09:52.480 IApp[2527:307] 1

What is the problem?

Thanks

Bert F
  • 85,407
  • 12
  • 106
  • 123
Gerardo
  • 5,800
  • 11
  • 66
  • 94

4 Answers4

6

After the release, the object is destroyed, so calling 'retaincount' a 2nd time has undefined behavior

Kris Van Bael
  • 2,842
  • 1
  • 18
  • 19
4

What is the problem?

The problem is that you are using retainCount and expecting a meaningful result.

Do not call retainCount

When to use -retainCount?

The above has some good details. So does one of the answers here:

https://stackoverflow.com/questions/4580684/common-programming-mistakes-for-objective-c-developers-to-avoid


Note that you can set the MallocScribble environment variable and this will cause allocated memory to be filled with 0xaa bytes on allocation and 0x55 bytes on deallocation. In the face of that, your second call to retainCount would crash.

Community
  • 1
  • 1
bbum
  • 162,346
  • 23
  • 271
  • 359
3

When you release the first time, the retain count is 1. Since the memory is about to be deallocated, there is no "need" to decrement the retain count, so the underlying code may simply skip the decrement step and deallocate the memory.

When you peek at the retain count the second time, you are looking at deallocated memory, which is unsafe and could potentially return any value. Since its immediately after the release, the memory probably hasn't been allocated to something else, but you shouldn't be accessing it regardless.

HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
Bert F
  • 85,407
  • 12
  • 106
  • 123
3

The objects are not released immediately. Probably there has to be a run loop cycle before the objects are really released.
However calling retainCount is really a mean thing. Please read why: When to use -retainCount?

EDIT: @kris-van-bael commented on this answer - correctly - that based on the documentation this is not true. So I have to clearly state that what I wrote here is based on testing this issue on iOS simulator - and it's not how it should things work. However it seems that the following code will run without an error:

@interface Test : NSObject { }
@property (retain, nonatomic) NSString *test;
@end

@implementation Test
@synthesize test;
@end

Then somewhere in your code write:

Test* t = [[Test alloc] init];
t.test = @"Test1";

NSLog(@"%@", t.test);

[t release];

t.test = @"Test2";

NSLog(@"%@", t.test);    

This (unfortunatelly) will run with no error on iOS simulator (however executing it step-by-step with the debugger crashes), so there is clearly some trick on deallocating objects in iOS.

Community
  • 1
  • 1
Moszi
  • 3,236
  • 2
  • 22
  • 20
  • That is incorrect, 'autorelease' is postponed 'till the end of the eventhandling but 'release' is performed immediately. – Kris Van Bael Jan 11 '11 at 22:34
  • Yes. That is the theory, and it should be true in all situations. However I've just created a small iOS application (tested in simulator), and after releasing my instance of my Test class, i still was able to get my properties value. It seems that the framework makes some delaying on invoking the dealloc... If you execute the program step-by-step you'll get a proper BAD ACESS though (try it ;) ...) – Moszi Jan 11 '11 at 22:42
  • 1
    `release` is immediate. The problem is that the behavior after `dealloc` is undefined. The system doesn't waste cycles scribbling on deallocated memory and, thus, "undefined" might mean "still semi-viable". – bbum Jan 11 '11 at 23:25
  • @bbum - so you are saying that the memory was deallocated, jut nothing changed that memory location ? this might be an answer as well ... – Moszi Jan 11 '11 at 23:30
  • @Moszi - Just because those properties don't look changed is not an indication that the memory hasn't been been deallocated. Deallocating doesn't clear the memory, it simply makes it available for allocation again. Reading those properties is accessing memory that could haven been allocated and overwritten already. Just because it isn't reallocated and overwritten during one particular run of a program doesn't mean it won't be the next time, especially under low-memory conditions. Its Russian roulette... – Bert F Jan 11 '11 at 23:40