iOS objective-C, same memory address after releasing an object - ios

I'm learning objective-c manual memory management. I have the following example:
int main(int argc, const char * argv[]) {
#autoreleasepool {
NSObject *o = [[NSObject alloc] init];
NSLog(#"%#", o);
[o release];
NSLog(#"%#", o);
}
return 0;
}
The output for this code is:
2015-07-31 16:18:34.694 test[2378:96008] <NSObject: 0x10020d110>
2015-07-31 16:18:34.696 test[2378:96008] <NSObject: 0x10020d110>
How is it possible, that after calling 'release' object is still present in memory (has the same address as before calling 'release') and NSLog does NOT give me EXC_BAD_ACCESS exception ?

That's because o still points to 0x10020d110, even after you've released the object.
Releasing an object does not change references to that object to nil, but they are invalid and if you attempted to send a message via the reference, undefined behaviour would ensue.
In your case, however it does not crash, as both NSLog() calls are calling [o description].

Related

The autoreleasepool with ARC in iOS

In iOS, when the autoreleasepool create and be destroyed?
When a touch event created, the runloop create an autoreleasepool.
When the touch event ends, the autoreleasepool will be destroyed.
Is my understand of the autoreleasepool right?
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
how can I understand the autoreleasepool in main method?
In xcode 4 we have to create pool and we have release it by using this syntax with NSAutorealeasePool:
{
NSAutorealeasePool *pool=[[NSAutorealeasePool alloc] init];
[pool drain];
}
When ever use like this in Xcode 4 memory is initialized for your pool and control enter into your pool deallocate your pool objects by using drain ..if u use drain means u permanently destroy ypur pool objects..if you use release means its not completely destroyed..
In xcode 5 we are using #autoreleasepool syntax like this:
#autoreleasepool
{
}
Here we don't need to create pool and release the objects..every thing done by compiler..once control enters automatically create the pool and release the pool objects means which we want to deallocate
The NSAutoreleasePool class is used to support Cocoa’s reference-counted memory management system. An autorelease pool stores objects that are sent a release message when the pool itself is drained.
IMPORTANT
If you use Automatic Reference Counting (ARC), you cannot use autorelease pools directly. Instead, you use #autoreleasepool blocks. For example, in place of:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Code benefitting from a local autorelease pool.
[pool release];
you would write:
#autoreleasepool {
// Code benefitting from a local autorelease pool.
}
#autoreleasepool blocks are more efficient than using an instance of NSAutoreleasePool directly; you can also use them even if you do not use ARC.
Few things to keep in mind -
Case 1)
#autoreleasepool
{
MyObject *obj = [[MyObject alloc] init];
//No need to do anything once the obj variable is out of scope there are no strong pointers so the memory will free
}
case 2)
MyObject *obj //strong pointer from elsewhere in scope
#autoreleasepool
{
obj = [[MyObject alloc] init];
//Not freed still has a strong pointer
}

Obj C: Unable to access singleton from debugger

So this is very odd. I just created a new singleton in my app, using the same pattern I have used for the numerous other singletons. This one, however, doesn't play nice with the debugger. Here's the code for getting the singleton:
- (id)init
{
self = [super init];
if (self) {
[self loadData];
}
return self;
}
+ (Settings *)sharedInstance
{
static Settings *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
// Do any other initialisation stuff here
});
return sharedInstance;
}
Now when I try to access the object from the debugger, it gives me this:
error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0x20).
The process has been returned to the state before expression evaluation.
Obviously, I wasn't trying to just get a handle on the singleton from the debugger, I was trying to get a property. This gives some even more interesting output:
(lldb) po [Settings sharedInstance].jpegCompressionLevel
error: warning: got name from symbols: Settings
warning: receiver type 'void *' is not 'id' or interface pointer, consider casting it to 'id'
error: no known method '-sharedInstance'; cast the message send to the method's return type
error: 1 errors parsing expression
What in the world is going on here? Calls from within code seem to go just fine. The debugger constantly fails though. In the same context, I'm able to access other singletons (using the same pattern) just fine.
It may be worth noting that the loadData method just loads a dictionary from disk, and that the getters for the properties on the class utilise the values in that dictionary, rather than ivars.
Here's the code for loadData:
-(void)loadData
{
// Load data from persistent storage
NSString *path = [self pathToDataFile];
NSMutableDictionary *settingsDict = [NSMutableDictionary dictionaryWithDictionary:[NSKeyedUnarchiver unarchiveObjectWithFile:path]];
_settingsDict = settingsDict;
}
Now I can't explain why, but renaming the class from 'Settings' to something else fixed the issue. I can't see anything in the Symbol Navigator that would clash with this name... very weird indeed.

Why does block object not dealloc the same way NSObject does?

Here's a code snippet that illustrates the problem
__weak id ptr = nil;
__weak id ptr2 = nil;
#autoreleasepool {
void (^block)(void) = [^{
NSLog(#"hahaha");
} copy];
block();
[[(id)block rac_willDeallocSignal] subscribeCompleted:^{
NSLog(#"block will dealloc");
}];
ptr = block;
int blockRetainCount = CFGetRetainCount((__bridge CFTypeRef)block);
NSObject *obj = [[NSObject alloc] init];
[obj.rac_willDeallocSignal subscribeCompleted:^{
NSLog(#"Obj dealloc");
}];
ptr2 = obj;
int objRetainCount = CFGetRetainCount((__bridge CFTypeRef)obj);
NSLog(#"oK");
}
NSLog(#"after pool %# %#" , ptr, ptr2);
When I run this snippet, I will see Obj dealloc printed to the console but not block will dealloc. After the autorelease pool also I will see ptr still containing a valid refence to the block while ptr2 has been correctly reset to nil as expected. Why is there this difference? When do blocks get dealloc'ed at all?
Multiple problems that should convince you to not ever try such a thing:
One, CFGetRetainCount isn't guaranteed to return anything meaningful in the presence of ARC.
Two, there is no guarantee that a block uses retain counts at all. Blocks that don't capture any variables are allocated as static variables; copy, retain and so on do nothing at all to them, and they are never allocated or deallocated.
Third, there is no guarantee that any block will ever call dealloc when it is deallocated. And no guarantee that it will happen in the next OS or iOS version.

IOS What executes before main()?

objc[1655]: Object 0x2314e0 of class __NSCFString autoreleased with no
pool in place - just leaking - break on objc_autoreleaseNoPool() to
debug
objc[1655]: Object 0x2315e0 of class NSPathStore2 autoreleased with
no pool in place - just leaking - break on objc_autoreleaseNoPool() to
debug
objc[1655]: Object 0x2316b0 of class __NSCFData autoreleased with no
pool in place - just leaking - break on objc_autoreleaseNoPool() to
debug
File:MultiFormatReader.mm Method:+[MultiFormatReader load] --
objc[1655]: Object 0x2317e0 of class __NSCFString autoreleased with
no pool in place - just leaking - break on objc_autoreleaseNoPool()
to debug
objc[1655]: Object 0x231800 of class __NSCFData autoreleased with no
pool in place - just leaking
- break on objc_autoreleaseNoPool() to debug
..++++++++
File:main.mm Method:main -- mark..
File:BarcodesAppDelegate.m Method:-[BarcodesAppDelegate
application:didFinishLaunchingWithOptions:] -
File:BarcodesAppDelegate.m Method:-[BarcodesAppDelegate
application:didFinishLaunchingWithOptions:] -
This is the relative code:
+ (void)load {
MPLog(#" ..++++++++");
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[FormatReader registerFormatReader:[[[self alloc] init] autorelease]];
[pool drain];
}
int main(int argc, char *argv[]) {
MPLog(#"mark..");
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
This my debug message,I used zxing framework in my APP,But I found before main() method execute, some other code executed already. Why? generally speaking, what executes before main()?
What does this program " objc[1655]: Object 0x2314e0 of class __NSCFString autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool() to debug" mean?
Move the 2 MPLogs below NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];?
+ (void)load {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
MPLog(#" ..++++++++");
[FormatReader registerFormatReader:[[[self alloc] init] autorelease]];
[pool drain];
}
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
MPLog(#"mark..");
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
Set a symbolic breakpoint at objc_autoreleaseNoPool to halt execution when this error is encountered. Then you can determine where you need to place your autorelease pools (explicitly).
generally speaking, what excutes before main()?
from +[NSObject load] docs:
Invoked whenever a class or category is added to the Objective-C
runtime; implement this method to perform class-specific behavior upon
loading.
+ (void)load
Discussion The load message is sent to classes and categories that are both dynamically loaded and statically linked, but only if the newly loaded class or category implements a method that can respond.
The order of initialization is as follows:
All initializers in any framework you link to.
All +load methods in your image.
All C++ static initializers and C/C++ __attribute__(constructor) functions in your image.
All initializers in frameworks that link to you.
In addition:
A class’s +load method is called after all of its superclasses’ +load methods.
A category +load method is called after the class’s own +load method.
In a custom implementation of load you can therefore safely message other unrelated classes from the same image, but any load methods implemented by those classes may not have run yet.
I'm seeing this same problem. If I put a breakpoint at objc_autoreleaseNoPool, on the main thread, I get the following useless stack trace:
0 0x332097b8 in objc_autoreleaseNoPool ()
1 0x331fe7b8 in (anonymous namespace)::AutoreleasePoolPage::autoreleaseSlow(objc_object*) ()
2 0x332098de in _ZL22_objc_rootAutorelease2P11objc_object ()
3 0x331fcdb6 in _objc_rootAutorelease ()
It seems to be hitting the autorelease error before anything in the application has actually started. Could this be the result of some load methods in one of the frameworks I have included in the project?

Why does Xcode 4.2 use #autoreleasepool in main.m instead of NSAutoreleasePool?

I've noticed that there is a different way in Xcode 4.2 to start the main function:
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil,
NSStringFromClass([PlistAppDelegate class]));
}
}
and
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
Does anybody know the difference between those two?
The first one is using ARC, which is implemented in iOS5 and above to handle memory management for you.
On the second one, you're managing your own memory and creating an autorelease pool to handle every autorelease that happens inside your main function.
So after reading a bit on what's new on Obj-C with iOS5 it appears that the:
#autoreleasepool {
//some code
}
works the same as
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// some code
[pool release];
with the difference that the last one would throw an error on ARC.
EDIT:
The first one is using ARC or not.

Resources