Could some one tell me why the memory address of the localComplete block and the self.block are the same? self.complete's property is set to copy, and just to be sure i also call copy on localComplete when assigning it to self.complete.
- (void) test {
CompletionBlock localComplete = ^{
};
NSLog(#"localComplete - %p", localComplete);
self.block = [localComplete copy];
NSLog(#"self.complete - %p", self.block);
self.block();
}
Here is the output:
2013-10-05 08:39:18.549 TestApp[90703:a0b] localComplete - 0x60b8
2013-10-05 08:39:18.550 TestApp[90703:a0b] self.complete - 0x60b8
As another example I create strings:
// creating string
self.carType = [[NSString alloc] initWithFormat: #"Good%#", #"year"];
NSLog(#"self.carType - %p", self.carType);
// same memory address???
NSString *carInitString = [[NSString alloc] initWithString: self.carType];
NSLog(#"carInitString - %p", carInitString);
// same memory address???
NSString *carCopy = [self.carType copy];
NSLog(#"carCopy - %p", carCopy);
// different memory address
NSString *carInitWithFormat = [[NSString alloc] initWithFormat: #"%#", self.carType];
NSLog(#"carInitWithFormat - %p", carInitWithFormat);
And the output:
2013-10-05 09:45:01.667 TestApp[91103:a0b] self.carType - 0xa084910
2013-10-05 09:45:01.668 TestApp[91103:a0b] carInitString - 0xa084910
2013-10-05 09:45:01.668 TestApp[91103:a0b] carCopy - 0xa084910
2013-10-05 09:45:01.668 TestApp[91103:a0b] carInitWithFormat - 0xa336b70
Why isn't carInitString and carCopy different memory addresses? Optimizations are turned off in the projects build settings.
Concerning your original question, blocks are normally allocated on the stack. Copying a block (either with the Block_Copy function or the -copy method) will move the block on the stack (further calls will just increase the block's retain count)
Block_copy [...], given a block pointer, either copies the underlying block object to the heap, setting its reference count to 1 and returning the new block pointer, or (if the block object is already on the heap) increases its reference count by 1
(source)
So in your example, you may expect different addresses, since the first block is local, whereas the second one is on the heap, BUT since that specific block doesn't make any reference to the surrounding scope, the compiler will mark it as a global block. Global blocks are not allocated on the stack, and are instead at a fixed location in memory.
Copying a global block won't move the block anywhere. It will just increase its retain count, since the object is already on the heap. That's why you don't get two different addresses.
Try to make a block with a reference to the surrounding context and you will have two different addresses (stack and heap).
Now, let's address your question about NSString.
Copying an immutable object can result in a retain as an optimization (I mean, a framework design optimization, the compiler has nothing to do with it), depending on how the class implements the NSCopying protocol.
This is true for many Foundation classes like NSString, NSArray, NSSet...
This is perfectly compliant with the NSCopying protocol specification, as you can read in the documentation:
Your options for implementing this protocol are as follows:
...
Implement NSCopying by retaining the original instead of creating a new copy when the class and its contents are immutable.
As noted by Greg Parker in the comments, -[NSString initWithString:] performs the same kind of optimization. If you pass an immutable string as argument, it just retains and return the same string.
This is a useful behavior in a few situations, here's an example: you declare a property
#property (nonatomic, copy) NSArray *anArray;
and you expose it in the interface.
Declaring it as copy is a good practice in order to ensure that the object you are working on doesn't get changed by the client later on. If you just retain it and the client passes in a NSMutableArray you cannot prevent her to manipulate the object.
So copying is good, but it looks like it comes with a price: you are going to copy the object even when you don't need to (i.e. it's immutable).
Thanks to the behavior discussed above, however, you don't pay such price. Sending copy to an NSArray will just retain it, whereas sending it to a NSMutableArray will actually copy it, so in this case is a big win.
it could be because the copy isn't necessary. you don't capture any variables or anything like that. so perhaps the block is constant. try having it refer to a local or __block variable.
Related
Transitioning to ARC on iOS.
I have an autoreleased NSString that I use to generate a UTF-8 representation, and rely on pool lifetime to keep the UTF-8 pointer alive:
char *GetStringBuffer(something)
{
NSString *ns = [NSString stringWithSomething:something];
return [ns UTF8String];
}
The nature of something is not important here.
Pre-ARC rules make sure the returned data pointer will stay valid for the lifetime of current autorelease pool. Crucially, I don't carry the NSString pointer around.
Now, under ARC, won't the string be released when the function returns? I don't think ARC will consider a char * to a structure deep inside an NSString a strong reference, especially seeing that it's not explicitly freed ever.
What's the best ARC idiom here?
If you want to guarantee that the return value of UTF8String is valid until the current autorelease pool is drained, you have two options:
Define GetStringBuffer in a file that is compiled with ARC disabled. If stringWithSomething: follows convention, it must return an autoreleased NSString to a non-ARC caller. If it doesn't (e.g. it acts like -[NSArray objectAtIndex:]), you can explicitly retain and autorelease it.
Use toll-free bridging and CFAutorelease:
char *GetStringBuffer(something) {
NSString *ns = [NSString stringWithSomething:something];
CFAutorelease(CFBridgingRetain(ns));
return [ns UTF8String];
}
(I can't delete this because it's accepted, but this answer is incorrect. See Rob Mayoff's answer, and the comments on that answer for an explanation. There is no promise that this pointer is valid past the return statement.)
Rewriting my whole answer. Had to dig and dig, but I believe this is surprisingly safe today (due to improvements in ARC since I had my crashes; I knew something like that was rolling around in the back of my head). Here's why:
#property (readonly) __strong const char *UTF8String NS_RETURNS_INNER_POINTER; // Convenience to return null-terminated UTF8 representation
UTF8String is marked NS_RETURNS_INNER_POINTER, which is really objc_returns_inner_pointer. Calling that method:
the object’s lifetime will be extended until at least the earliest of:
the last use of the returned pointer, or any pointer derived from it, in the calling function or
the autorelease pool is restored to a previous state.
Which is pretty much what you wanted it to do.
I am a newbie to Objective-C. XCode highlights the following code as an issue.
_myCookies is a private variable of my class where I store the received cookies.
#implementation MessageSender {
NSArray *_myCookies;
}
...
// Socket open callback
- (void) gotData:(MySocket *) socket {
NSDictionary *responseHeaders = (__bridge NSDictionary*)CFHTTPMessageCopyAllHeaderFields(socket.HTTPHeaders);
_myCookies = [NSHTTPCookie cookiesWithResponseHeaderFields:responseHeaders
forURL:[NSURL URLWithString:#""]];
}
The highlighted issues are:
Call to function 'CFHTTPMessageCopyAllHeaderFields' returns a Core Foundation object with a +1 retain count
Object leaked: object allocated and stored into 'responseHeaders' is not referenced later in this execution path and has a retain count of +1
How do I resolve this one?
I am using ARC. I want to store the cookies in my class so I can later use them while sending the request, but I want to let the socket take care of its responseHeaders.
You need to transfer ownership of the CoreFoundation object to ARC:
NSDictionary *responseHeaders = CFBridgingRelease(CFHTTPMessageCopyAllHeaderFields(socket.HTTPHeaders));
CF objects are not managed by ARC, and must be released manually. When you use a __bridge cast, you're simply casting the object directly with no change in ownership. This is what causes your memory leak (you need to manually release CF objects with CFRelease when you're done with them).
You can avoid all this manual memory management trouble by simply using CFBridgingRelease to cast the object (as in the code example above). This transfers ownership of the CF object to ARC, so ARC will automatically handle releasing that object for you, and everything will work just fine with no extra work on your part.
Instead of __bridge, use __bridge_transfer which transfers ownership of the object to ARC. Ex:
NSDictionary *responseHeaders = (__bridge_transfer NSDictionary*)CFHTTPMessageCopyAllHeaderFields(socket.HTTPHeaders);
In Apple's documentation about ARC, they make a point of spelling out a problematic scenario in which ARC will generate a boilerplate temporary variable behind the scenes. Search on "The compiler therefore rewrites":
https://developer.apple.com/library/mac/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html
The gist of the warning seems to be that because the stack-based variable is "strong" and the by-reference parameter to the called method (performOperationWithError:) is autoreleasing, ARC will generate a temporary local variable to serve the memory management needs of the autoreleasing variable. But because the temporary variable is assigned to the strong variable in the boilerplate example, it seems as though from a client's point of view there is no risk.
What exactly is the documentation taking pains to warn us about here? What is the risk as either a client or as an implementor of a method that may be called in this way (with an autoreleased, return-by-value parameter)?
It's only a warning about less than ideal performance. In the rewritten code, the NSError pointed to by "tmp" comes back autoreleased, is retained when assigned to "error", and then is released again when "error" goes out of scope.
If you change the declaration in the original code to:
NSError __autoreleasing *error;
If you do this, there is no assignment to a temp, and that implicit retain and then release no longer occurs. (The NSError object itself is still valid for exactly as long as it was before, since it is still in the autorelease pool.) So the documentation is warning you that if you use the "wrong" variable qualifier that it can cause extra retain count munging that wouldn't otherwise be required.
Also note that with either version of the code: Because the variable in question is passed by reference and isn't the return value from -performOperationWithError:, there isn't the opportunity to do the magic stack walking trick that ARC can do to save the object from going into the autorelease pool in the first place.
I think it’s to prevent confusion if you start looking at the values passed into the method. In their example, if I set a breakpoint on the line that calls [myObject performOperationWithError:&tmp]; and type p error, I’ll see the address of it. But if I step into -performOperationWithError: and type p error, I’ll get a different value—inside the method, error points to that temporary value.
I can see a situation where some poor sap is trying to debug something tricky with ARC where the pointer changing as it gets passed into the method would be an extremely confusing red herring.
My guess: If you made assumptions about the memory referenced by the output parameter, e.g indexing off the pointer, you might be surprised.
I don't think it has anything to do with the client. It looks like a reference to the same issue addressed in the WWDC 2013 video on memory issues: If you yourself implement a method that takes an autoreleasing indirection parameter (such as an NSError**), and if you create an autorelease pool block inside that method, do not assign to the NSError from inside the autorelease pool block. Instead, assign to a local variable, and then assign from the local to the NSError outside the autorelease pool block.
Seems to me that it's less of a warning about this behavior than a description of what the compiler does in this case and why you can pass the address of a strong local error reference to a method that is declared as wanting an __autoreleasing reference and not trigger a complaint.
You generally want an API to use __autoreleasing on such a parameter in case it is being used by either ARC or non-ARC code, as in non-ARC code it would be unusual to have to release such an output parameter.
The Apple documentation is referring to a compiler misfeature that will synthesize a temporary variable for you to deal with the conversion between __block and __autoreleasing. Sadly, this doesn't solve very many problems and it produces potentially disasterous unexpected results.
For example:
int main(int argc, char *argv[])
{
__block id value = #"initial value";
void (^block)(id *outValue) = ^(id *outValue){
value = #"hello";
};
block(&value);
NSLog(#"value = %#", value);
return 0;
}
With ARC, this reports:
2013-04-24 13:55:35.814 block-local-address[28013:707] value = initial value
but with MRR:
2013-04-24 13:57:26.058 block-local-address[28046:707] value = hello
This very often comes up when using NSFileCoordinator, causing you to lose the resulting NSError!
#import <Foundation/Foundation.h>
int main(int argc, char *argv[])
{
NSURL *fileURL = [NSURL fileURLWithPath:#"/tmp/foo"];
NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
__block NSError *error;
[coordinator coordinateWritingItemAtURL:fileURL options:0 error:&error byAccessor:^(NSURL *newURL){
NSDictionary *userInfo = #{
NSLocalizedDescriptionKey : #"Testing bubbling an error out from a file coordination block."
};
error = [NSError errorWithDomain:NSPOSIXErrorDomain code:ENOSYS userInfo:userInfo];
}];
NSLog(#"error = %#", error);
}
When compiled with ARC, this results in a nil error!
This has been written up as a bug at llvm.org for a while, though I just changed the title to make it more clear that I'm suggesting the feature be ripped out. Also attached to that bug is a patch to add a new flag -fno-objc-arc-writeback to disable the feature).
I found a strange behavior with NSString. I tried to run the below code and noticed this.
NSString *str = [[NSString alloc] initwithstring : #"hello"];
[str release];
NSLog(#" Print the value : %#", str);
Here, in the third line app should crash because we are accessing an object which is released. But it is printing the value of str. It is not crashing. But with NSArray i observed different behavior.
NSArray *array = [[NSArray alloc] initwithobjects : #"1", #"2", nil];
[array release];
NSLog(#"Print : %#", [array objectatindex : 0]);
NSLog(#"Print : %#", [array objectatindex : 0]);
The code has two NSLog statements used for NSArray. Here after releasing when the first NSLog is executed, it is printing value. But when second NSLog is executed, app crashes. App crash is acceptable because the array accessed was released already. But it should crash when the first NSLog is executed. Not the second one.
Help me with this behaviors. How release works in these cases.
Thanks
Jithen
The first example doesn't crash because string literals are never released. The code is really:
NSString *str = #"hello";
[str release];
People get burned with string literals on memory management and mistakenly using == to compare them instead of isEqualToString:. The compiler does some optimizations that lead to misleading results.
Update:
The following code proves my point:
NSString *literal = #"foo";
NSString *second = [NSString stringWithString:literal];
NSString *third = [NSString stringWithString:#"foo"]; // <-- this gives a compiler warning for being redundant
NSLog(#"literal = %p", literal);
NSLog(#"second = %p", second);
NSLog(#"third = %p", third);
This code gives the following output:
2013-02-28 22:03:35.663 SelCast[85617:11303] literal = 0x359c
2013-02-28 22:03:35.666 SelCast[85617:11303] second = 0x359c
2013-02-28 22:03:35.668 SelCast[85617:11303] third = 0x359c
Notice that all three variable point to the same memory.
Your second example crashes at the second NSLog because at the first log, the memory where array was hasn't been re-used, but that first log causes enough activity on the heap to cause the memory to become used by something else. Then, when you try to access it again, you get a crash.
Whenever an object is deallocated and its memory marked as free, there is going to be some period of time where that memory still stores what's left of that object. During this time you can still call methods on such objects and so forth, without crashing. This time is extremely short, and if you're running a lot of threads it may not even be enough to get your method call in. So clearly, don't rely on this implementation detail for any behavior.
As others have said, regarding your first question, NSString literals aren't going to be deallocated. This is true for some other Foundation classes (NSNumber comes to mind) but is an implementation detail as well. If you need to do experiments on memory management, use an NSObject instance instead, as it will not show the unusual behaviors.
When you send a release message on an object, the object is actually not being removed from the memory. The release message simply decrements the reference count by one only. If the reference count is zero the object is marked as free. Then the system remove it from the memory. Until this deallocation happens you can access your object. Even if you release the object your object pointer still points to the object unless you are assigning nil to the pointer.
The first example doesn't crash because string literals are never released. Where the second totally depends on release and retain counter.
Read this article. Its contains short-and-sweet explanation for your query
You Should read this apple guideline
You seem to assume that release should destroy the object immediately. I don't think that's the guarantee that the language makes. What release means is: I have finished using this object and I promise not to use it again. From that point onwards it's up to the system to decide when to actually deallocate the memory.
Any behaviour you see beyond that is not defined and may change from one version of the Objective C runtime to the next.
That's to say that the other answers that suggest the difference is string literals and re-use of memory are currently correct but assuming that the behaviour will always be like this would likely be a mistake.
I'm trying to find the size of an objective-c object. I'm using something similar to:
NSLog(#"sizeof myObject: %ld", sizeof(*myObject));
That just gives me the size of the pointer though.
What am I doing wrong?
All the compiler knows about is the pointer, which is why you're getting the size of the pointer back. To see the size of the allocated object, use one of the following code snippets:
With ARC:
#import <malloc/malloc.h>
// ...
NSLog(#"Size of %#: %zd", NSStringFromClass([myObject class]), malloc_size((__bridge const void *) myObject));
Without ARC:
#import <malloc/malloc.h>
// ...
NSLog(#"size of myObject: %zd", malloc_size(myObject));
Mike Ash has a decent write-up about some of the Obj-C runtime internals on his Q&A blog: http://mikeash.com/?page=pyblog/friday-qa-2009-03-13-intro-to-the-objective-c-runtime.html
In the GNU Objective-C runtime, you can use (you must import <objc/objc-api.h>:
class_get_instance_size ([MyClass class]);
On Mac OS X you can use (you might need to import <objc/runtime.h>):
class_getInstanceSize ([MyClass class]);
These functions will return how much memory is required to allocate an object, it will not include memory allocated by an object when it is initialised.
First of all, i think its clear from the above posts that the object size is given by malloc_size(myObject), as suggested by Jason and also on the Mac OS reference manual:
"The malloc_size(ptr) function returns the size of the memory block that backs the allocation pointed to by
ptr. The memory block size is always at least as large as the allocation it backs, and may be larger." (http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/malloc_size.3.html)
But if you are interested in finding out the size of the dictionary, keep in mind the following point:
The dictionary stores key-value pairs and does not contain the object itself in the value part but just increases a retain count of the object that was to be "added" and keeps a reference of that object with itself. Now, the dictionary itself just contains the references to the various objects (with a key attached). So if by any chance you are looking for the object size of all the objects refered to by the dictionary, technically that would not be the size of the dictionary. The size of the dictionary would be the sum of the size of all the keys plus the size of all the value-references against the keys plus the size of the parent NSObject. If you are still interested in finding out the size of the refered objects as well, try iterating over the dictionary values array:
NSArray *myArray = [myDictionary allValues];
id obj = nil;
int totalSize = 0;
for(obj in myArray)
{
totalSize += malloc_size(obj);
}
//totalSize now contains the total object size of the refered objects in the dictionary.
Hope that answers the question.
The size of an (objective-c) object is not easy to find because it's not even easy to define. What did you mean with "size of an objective-c object"?
The size of the reference is the size of a pointer (as returned by sizeof(obj_ref)).
The size of the memory that was allocated on creation (+alloc) may be found by the way that Jason gave in the first answer. But this depends on the runtime. The gnu-runtime differs from the apple-runtime. Eventually this is only the memory that is needed by the primitive data types the instance consists of. But not the memory that may be allocated later on (i.e. during initialization (-init)) for objects referenced by the ivars or strings.
An instance of the class
#interface FirstClass
{
int _someInt;
char _someChar;
}
…
#end
needs at least 5 bytes (on many systems - int size may vary) plus static overhead if the runtime needs it. The size of such an object is obvious.
But for an instance of the class
#interface SecondClass
{
FirstClass *_someObject;
char *_name;
id _data;
}
…
#end
the definition of the "size" ist complicated. The object needs 12 bytes (on 32bit systems) plus overhead on allocation. But maybe the name is part of the object and allocated/freed by it. Should the memory which the actual name needs be part of the object's size? And what about the referenced objects?
I would suggest using class_getInstanceSize and malloc_good_size to see what it'll round up to. This will not show the ivars and whatnot inside the returned size.
#import <malloc/malloc.h>
#import <objc/runtime.h>
NSLog(#"Object Size: %zd", malloc_good_size(class_getInstanceSize([yourObject class])));
I think the class description contains the size information -- it is better to look this up than querying using the sizeof operator.