Objective-C release is not called explicitly

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSString * str = [[NSString alloc] initWithString:@"test"]; [str release]; int i = 999999999; while(i-- > 0) {} NSLog(@"%@", str); [pool drain]; 

Output: test

Why didn’t release ? How can I immediately delete an object from memory?

App for iPhone Xcode version 4.0

<h / "> ~ ~ SOLVE

Thanks everyone for the answers. I have a lot of useful information about this issue. I am going to use NSString * str = @ "text" instead of NSString * str = [[NSString alloc] initWithString: @ "text"];

I realized that the release simply "marks" the memory as "ready to be freed," but without releasing it immediately

+4
source share
5 answers

It worked. You have given up ownership of this object, and when the system determines that it no longer belongs, it will be marked for reuse by the system. This can happen immediately if you were the sole owner of the string. This can happen at some later point if the creation of the string caused its auto-implementation inside. Or, as Dave DeLong points out, the system can optimize it into an object that is never released.

In your case, it is optimized into a constant string that will exist for the life of the program. If you were to use NSMutableString instead of NSString , you would notice funny behavior that probably won't crash but won't print what you expected. (See this question for an example.)

If you used NSArray instead, it would be freed when you call release , but you will still see that your NSLog example works correctly until you select any other object. Deallocation simply marks the memory as reusable; in fact, this is not clear. Therefore, if you passed an array to NSLog, that memory was not changed and therefore it still prints correctly.

The key to all of this, however, is recognizing that calling release does not necessarily cause the object to be freed. It can continue to exist for a number of reasons. But as soon as you call release , you have lost ownership of the object. If you continue to use it after this point, the system can do all kinds of strange things of its own free will, as shown.

+6
source

Vacation works, but what you are trying to do has undefined behavior, and when using NSString and a literal, you can also get different behavior. What happens, although your object is released, the memory in this place is fixed and has not changed, and when it goes for printing, it is still valid. Since this is an NSString, a description message is not necessarily sent, and that is why you are not getting an exception for trying to send a freed object.

This question contains some useful information about NSString and NSLog.

+6
source

When you do:

 NSString * str = [[NSString alloc] initWithString:@"test"]; 

This is optimized for:

 NSString * str = @"test"; 

You cannot release constant string because it is hard-coded into the application binary.

Evidence:

 NSString *s = [NSString alloc]; NSLog(@"%p", s); s = [s initWithString:@"foo"]; NSLog(@"%p", s); s = @"foo"; NSLog(@"%p", s); 

Logs:

 2011-04-12 10:17:45.591 EmptyFoundation[6679:a0f] 0x100116370 2011-04-12 10:17:45.599 EmptyFoundation[6679:a0f] 0x100009270 2011-04-12 10:17:45.604 EmptyFoundation[6679:a0f] 0x100009270 

You can see that the result of +alloc is different from the result of -initWithString: and the result of -initWithString: equivalent to a constant string. Basically, -initWithString: says "aha, I will be an immutable string, and they give me an immutable string! I can just take a shortcut, destroy myself and return the parameter, and everything will work the same"

+4
source

You are using a bad pointer in your NSLog (). You are lucky in this case, but you should expect code like this to crash or fail in other ways.

+1
source

There is no need to delete the memory block, this will use an unnecessary loop. The memory will be overridden when a new object is allocated to occupy this memory block.

0
source

Source: https://habr.com/ru/post/1347735/


All Articles