The code below works fine, I just don't know where the release should go, because I'm not sure what the rules are. I'm not using ARC.
- (void)myFunc {
// stuff happens
__block UIImage* photo = [UIImage imageWithCGImage:croppedCGImage];
[photo retain];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
(unsigned long)NULL), ^(void) {
[self doStuffToPhoto:photo];
// [photo release] causes EXC_BAD_ACCESS
});
// [photo release] causes EXC_BAD_ACCESS in doStuffToPhoto
}
- (void)doStuffToPhoto:(UIImage*)photo {
// do stuff
// [photo release] causes EXC_BAD_ACCESS
}
If I understand the docs right (look for The block Storage Type and Object and Block Variables here), there is no need to retain your photo variable: "__block variables live in storage that is shared between the lexical scope of the variable and all blocks and block copies declared or created within the variable’s lexical scope. Thus, the storage will survive the destruction of the stack frame if any copies of the blocks declared within the frame survive beyond the end of the frame".
But this no explanation why you get the EXC_BAD_ACCESS.
Related
File Person.h
#interface Person:NSObject
+ (void)callBlock:(void (^)())block;
#end
File Person.m
#imp:
+ (void)callBlock:(void (^)())block
{
[NSThread sleepForTimeInterval:2];
block();
}
#end
Code in ViewDidLoad:
Person *p = [[Person alloc] init];
void (^block)() = ^{
NSLog(#"%#",p);
[p release];
}
[Person callBlock:block];
finish!
MyQuestion:
in main function, block var is a stackblock,and this block assign to the function +callBlock:,and the block in Person.m is also a stackblock. Content of them are same.
In my opinion,the block in main will be free by system before called in Person.m, so I think this program will crash, but it run normal. why?
And i think my code is same as below.
...
void example_addBlockToArray(NSMutableArray *array) {
char b = 'B';
[array addObject:^{
printf("%cn", b);
}];
}
void example() {
NSMutableArray *array = [NSMutableArray array];
example_addBlockToArray(array);
void (^block)() = [array objectAtIndex:0];
block();
}
This programe crashed! which the difference between them?
Sorry! both program use mrc!!! i did not write clearly!
As it seems, you're using manual memory management.
Therefore is an explanation:
Person object case
You create the object
You create the block
You call the block
Block logs the object out
Block frees the object
That's why there is no crash
Char log case
Since you're not using ARC, it goes this way:
You add the block that logs char
Once you leave the function that adds the block to an array, the char you've just created is going to be released from memory.
In case if you use ARC for memory management, it will keep this char alive in the memory, until this block exists. But once you remove it from an array and block's reference count equals to 0, this char also being released.
You take a block from an array
Call it, it references to a memory address of char that already released, crash appears. As explained in your error:
EXC_BAD_ACCESS (code=1, address=0x0)
Means, that you point to zero address (null pointer exception in other words).
So, that's it.
As pointed out in the comments, the first example does not crash because the block is defined in a function scope which doesn't end until after the block is called.
The second example, on the other hand, defines the block in a secondary function, which ends before the block is called. Thus, at the time of the block invocation, the stack has already been modified and the block has become invalid.
After main function executed the block in main will be free by system ,not before called in Person.m. I tried the second code in viewcontroller, it works fine, not crash.
Here is the code below. It downloads a thumbnail image and then tries to create an image based on the thumbnail file path. But it gives me EXC_BAD_ACCESS error at method call "imageWithContentsOfFile". While EXC_BAD_ACCESS addresses the code trying to access an object that has been released most likely I don't know which object it could be. Any help'd be appreciated!
NSBlockOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{
if([[NSFileManager defaultManager] fileExistsAtPath:operation.destinationPath ]){
NSString *key = [[MEURLCacheKeyRegister sharedRegister] cacheKeyForURL:operation.fileUrl];
UIImage *image = [UIImage imageWithContentsOfFile:operation.destinationPath];
}else{
DDLogDebug(#"Thumbnail file doesn't exist at %#", operation.destinationPath);
}
}
}];
AFDownloadRequestOperation *requestOperation = [FileServerDownloadUtils downloadOperationForURL:operation.fileUrl
destinationPath:operation.destinationPath
completion:completionOperation];
[self.fileSyncQueue addOperation:requestOperation];
EXC_BAD_ACCESS indicates that object has been released while its being accessed.
If I were you, I would try following things:
Save the file with .jpg and not .jpg.prv.jpg extension.
Try using initWithContentsOfFile instead of imageWithContentsOfFile as imageWithContentsOfFile autoreleases image which in rare edge cases creates crashes like this.
When passing code to a block, access object properties by making weak reference to self. Something like this: __weak MyController *weakSelf = self. Then use weakSelf to access properties inside the block.
These are just few clues which may help you digging it further. You may use NSZombie and other profiling tools to nail it down.
I'm trying to figure out if I do this right:
If I have one block, I'll do this:
__weak MyClass *weakSelf = self;
[self performBlock:^{ //<< Should I use self, or weakSelf here?
[weakSelf doSomething];
} afterDelay:delay];
But what happens if there's a block in a block? Would this be correct?
__weak MyClass *weakSelf = self;
[self performBlock:^{
[weakSelf doSomething];
[self performBlock:^{
[weakSelf doSomething];
} afterDelay:1.0f];
} afterDelay:delay];
Also, in the function below, do I need to use [block copy]?
- (void)performBlock:(void (^)(void))block afterDelay:(float)delay
{
if (block)
{
if (delay > 0)
{
[self performSelector:#selector(executeBlockAfterDelay:) withObject:[block copy] afterDelay:delay];
}
else
{
[self executeBlockAfterDelay:[block copy]];
}
}
}
- (void)executeBlockAfterDelay:(void(^)(void))block
{
if (block)
block();
}
In this case (below) use just strong self, because the block is copied just for those few seconds. And usually if you want the self to perform block, you want to it to stay alive until that time, so strong reference is perfectly okay.
[self performBlock:^{
[self doSomething]; // strong is OK
} afterDelay:delay];
Block inside a block? In your case those two block are just delayed one-shot blocks, so the same as above, use strong. But there are differences between blocks. If you store the block for longer time, maybe for multiple invocations you should avoid retain-cycles.
Example:
self.callback = ^{
[self doSomething]; // should use weakSelf
};
This may cause retain-cycle. In fact it depends on how the block is used. We see that the block is stored (copied) in property for later use. However, you can prevent the retain-cycles by nullifying block that will not be used any more. In this case:
self.callback(); //invoke
self.callback = nil; //release
When using ARC, you don't have to copy blocks yourself. There were bugs in early versions after blocks were added, but now the compiler under ARC knows when to copy blocks. It is clever enough to copy it in this case:
[self performSelector:#selector(executeBlockAfterDelay:) withObject:block afterDelay:delay];
Rather than implementing -performBlock:afterDelay:, just use dipatch_after(). Among other things, that's not a message delivered to an object, so there's no question of what receiver to target it at.
Actually, there's no memory management issue here at all. One typically only needs to do a "weak self" approach when an object retains a block and the block (perhaps implicitly) retains that same object. However, the object is not retaining the block. It is being retained by the framework until the -performSelector:withObject:afterDelay: fires, but that's not a retain cycle.
If there were a retain cycle, then you should not reference self in the blocks. So, your nested case is wrong in invoking a message on self rather than weakSelf.
Finally, yes, you do need [block copy] whenever you are keeping a block after execution leaves the scope of its declaration or if you pass it to non-block-specific API that does. That is, you don't need to copy a block when you pass it to, say, dispatch_async() because that's a block-aware API that knows to make its own copy as necessary. But -performSelector:withObject:afterDelay: is not block-aware. It just treats its argument as a generic object and retains it. So, you do have to copy the block when passing it to that.
One the most important thing to understand about blocks is that they capture a piece of code (including values) in an abstract entity that can be manipulated as an atomic object (keep it somewhere, pass it, copy, etc...). Actually it is implemented in a way that guarantee that by default your block will remain valid and executable safely later.
Then capturing and retaining the required dependencies inside the block is necessary.
Unfortunately, in some cases (quite often actually) the block is retained by the instance that creates it and it retains itself that instance. This is called a retain loop and makes your object and your block impossible to dealloc unless you break one of the retaining relation yourself. This can happen if you reference your block with an instance variable for example and you don't nillify it manually.
This is probably the main issue with blocks especially because sometime, you don't know that your block retains your self instance (NSAssert within your block for example). Then:
If you execute your block immediately and release it (use your block
with dispatch release it after execution) there is no risk since you
are sure your object referenced by self still exist.
But if the execution is delayed it is important to retain your object within your block. But in that case your object should not retain your block to avoid a retain loop (A retains B and B retains A). If you define and optionally reference your block in the private scope of method it is perfect.
About copy. Yes it can be safer to use copy if your block in passed as a method argument to be sure you have a clean exclusive block in this scope with a +1 retainCount. But maybe ARC already do it for you. Not sure about that. For example it performWithSelector seems to do it for free, then copy is not dangerous. Just a useless. Sometime the compiler can optimise that by removing it but it has to be checked.
I usually do this:
__unsafe_unretained __block id blockSelf = self;
and then use it in my blocks no issues.
So in your case:
__unsafe_unretained __block MyClass *blockSelf = self;
[self performBlock:^{
[weakSelf doSomething];
[self performBlock:^{
[weakSelf doSomething];
} afterDelay:1.0f];
} afterDelay:delay];
Also to make your life a tad easier - make a utilities class and put this in the header
void RunAfterDelay(NSTimeInterval delayInSeconds, dispatch_block_t block);
and then this in the .m file
void RunAfterDelay(NSTimeInterval delayInSeconds, dispatch_block_t block)
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC), dispatch_get_main_queue(), block);
}
Import the utilities into your prefix and you can go:
__unsafe_unretained __block MyClass *blockSelf = self;
RunAfterDelay(1.0f,^{
[blockSelf doSomething];
RunAfterDelay(delay,^{
[blockSelf doSomething];
})
});
I find it a bit nicer to read than the verbose default ones.
Hope this helps :)
Hi I'm working through the Stanford iOS development class. I have a question regarding threading. I understand UIKit calls should be handled by the main thread. I was wondering if something like this is legal?
- (UIImage *)mapViewController:(MapViewController *)sender imageForAnnotation:(id<MKAnnotation>)annotation {
FlickrPhotoAnnotation *fpa = (FlickrPhotoAnnotation *) annotation;
NSURL *url = [FlickrFetcher urlForPhoto:fpa.photo format:FlickrPhotoFormatSquare];
__block UIImage *image;
dispatch_queue_t downloadQ = dispatch_queue_create("download queue", NULL);
dispatch_async(downloadQ, ^{
NSData *data = [NSData dataWithContentsOfURL:url];
if (data) {
dispatch_async(dispatch_get_main_queue(), ^{
image = [UIImage imageWithData:data];
});
}
});
dispatch_release(downloadQ);
return image;
}
or I should just return NSData and handle all the threading in the calling method?
Thanks
Your code won't do what you want.
You are putting an asynchronous block into a queue, and then immediately returning from the method. You are not guaranteed that the block will actually run before you return -- in fact, the odds are that it won't.
So you'll return the current value of image. Since you didn't initialize it, it's probably garbage. Whoever calls this method will try to use a garbage pointer to an image, and (if you're lucky) crash. If you had initialized it to nil:
__block UIImage *image = nil;
that would be a little more polite.
The problem here is: your method must return a UIImage, so you must wait for the time it takes to make a fully constructed UIImage before you return. There is zero benefit to doing this on some other thread -- you're still waiting the same amount of time, and switching threads just adds overhead.
In order to load the image in a usefully asynchronous way, you need some way to asynchronously tell the caller when the image is done loading, via a callback to a delegate method or block. For example, look at NSURLConnection in Foundation. It has an older method that calls back via a delegate, and a newer method (+sendAsynchronousRequest:queue:completionHandler:) that calls back via a block.
I concur with CodaFi's comment. Actually, images can be created off the main thread. UIView creation and manipulation must be done on the main thread, but UIImage is not a UIView though. Furthermore, the runtime is likely to give you a warning or error if you try to manipulate the displaying UI on another thread (it did for me when I accidentally updated a UITableView on another thread).
Mike Ash has written this introduction to ARC where he introduces something like:
__weak Foo *_weakFoo = [object foo];
Why would I want to do that for a local, temporary variable? __weak is a zeroing reference which will set the _weakFoo pointer automatically to nil as soon as the referenced object gets deallocated. Also, __weak is only available in iOS >= 5.
When would I run into trouble when I simply do this?:
Foo *_weakFoo = [object foo];
This is always expected to return an object or nil. My guess is this:
Foo *_weakFoo = [object foo];
[self doSomethingStupid]; // does something bad so foo gets deallocated
[_weakFoo doIt]; // CRASH! msg sent to deallocated instance 0x123456
One thing that still bugs me with ARC is: When does it know that I don't need an object anymore? I'd argue that when I set a pointer to nil or to something else it figures out that the previously referenced object isn't needed by this owner anymore and therefore maybe can go away. But the point is: I set it to nil. So it's nil anyways!
So when would __weak for a local variable make sense, and what kind of crazy thing must I do somewhere else so that I really need that?
I use __weak local variables if I have to manipulate self inside of a block to avoid a retain cycle. Consider this example where I'm using GCD and blocks to perform a network request for a string, and then setting it on a label declared by the class, in this case, TurtlesViewController.
__weak TurtlesViewController *weakSelf = self;
dispatch_queue_t networkQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(networkQueue, ^{
// Kick off a network task for some data that is going to populate a label declared on our class
NSString *returnString = [networkDataSource retrieveTurtleTime];
// Dispatch back to the main thread to populate the UILabel
dispatch_async(dispatch_get_main_queue(), ^{
// Using self.label here creates a retain cycle. Self owns the block and the block has captured self
self.label.text = returnString;
// Instead, we use weakSelf for our reference to the label as it will be torn down by ARC at the end of the loop.
weakSelf.label.text = returnString;
});
});