Static variable inside block - ios

What happens when I declare a static variable inside a block like this?
dispatch_async(dispatch_get_main_queue(), ^{
static NSInteger myNumber;
// do stuff with myNumber
});
What happens the second time this block is triggered?
How can myNumber be still there if the block will deallocate after running?
Is doing this OK? I mean will this practice cause any problem, like the block leaking because it is unable to be released?

The block specification does not explicitly mention how static variables within blocks are handled, just that the block body is a compound statement which is just the same as the body of a function. Therefore the semantics are the same as for static variables declared in a function, that is they are variables of global lifetime which are only directly accessible by name within the scope they are declared in.
A block value is constructed each time a block literal (^{...}) is evaluated. This value contains a standard C function pointer to the compiled code of the block body, which like any other compound statement is generated once at compile time.
The answers to your questions just follow from this:
What happens the second time this block is triggered?
Same thing that happens the second time a function with a local static variable is executed, the function body sees the value previously stored in the variable.
How can myNumber be still there if the block will deallocate after running?
Because it is the block value, which includes any associated captured variables, which is deallocated; the compiled code, which includes any static variables, always exists.
Is doing this OK? I mean will this practice cause any problem, like the block leaking because it is unable to be released?
Doing this is the same as doing it within a function. If the static is of Objective-C object type then references stored in it may "leak" - just as with standard global variables. The block value will not be prevented from deallocation unless you store a reference to the block itself (directly or indirectly via a chain of references) in the static variable.
HTH

maybe we can answer using "C" underlying logic.. closure-> blocks -> pointer to std C functions, to "C" static logic occurs-> globals (OMG!)

Related

Understand one edge case of block memory management in objc

the code below will crash because of EXC_BAD_ACCESS
typedef void(^myBlock)(void);
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *tmp = [self getBlockArray];
myBlock block = tmp[0];
block();
}
- (id)getBlockArray {
int val = 10;
//crash version
return [[NSArray alloc] initWithObjects:
^{NSLog(#"blk0:%d", val);},
^{NSLog(#"blk1:%d", val);}, nil];
//won't crash version
// return #[^{NSLog(#"block0: %d", val);}, ^{NSLog(#"block1: %d", val);}];
}
the code runs in iOS 9 with ARC enabled. And I was trying to figure out the reason that lead to crash.
by po tmp in lldb I found
(lldb) po tmp
<__NSArrayI 0x7fa0f1546330>(
<__NSMallocBlock__: 0x7fa0f15a0fd0>,
<__NSStackBlock__: 0x7fff524e2b60>
)
whereas in the won't crash version
(lldb) po tmp
<__NSArrayI 0x7f9db481e6a0>(
<__NSMallocBlock__: 0x7f9db27e09a0>,
<__NSMallocBlock__: 0x7f9db2718f50>
)
So the most possible reason I could come up with is when ARC release the NSStackBlock the crash happen. But why would so?
First, you need to understand that if you want to store a block past the scope where it's declared, you need to copy it and store the copy instead.
The reason for this because of an optimization where blocks which capture variables are initially located on the stack, rather than dynamically allocated like a regular object. (Let's ignore blocks which don't capture variables for the moment, since they can be implemented as a global instance.) So when you write a block literal, like foo = ^{ ...};, that's effectively like assigning to foo a pointer to a hidden local variable declared in that same scope, something like some_block_object_t hiddenVariable; foo = &hiddenVariable; This optimization reduces the number of object allocations in the many cases where a block is used synchronously and never outlives the scope where it was created.
Like a pointer to a local variable, if you bring the pointer outside the scope of the thing it pointed to, you have a dangling pointer, and dereferencing it leads to undefined behavior. Performing a copy on a block moves a stack to the heap if necessary, where it is memory-managed like all other Objective-C objects, and returns a pointer to the heap copy (and if the block is already a heap block or global block, it simply returns the same pointer).
Whether the particular compiler uses this optimization or not in a particular circumstance is an implementation detail, but you cannot assume anything about how it's implemented, so you must always copy if you store a block pointer in a place that will outlive the current scope (e.g. in a instance or global variable, or in a data structure that may outlive the scope). Even if you knew how it was implemented, and know that in a particular case copying is not necessary (e.g. it is a block that doesn't capture variables, or copying must already have been done), you should not rely on that, and you should still always copy when you store it in a place that will outlive the current scope, as good practice.
Passing a block as an argument to a function or method is somewhat complicated. If you pass a block pointer as an argument to a function parameter whose declared compile-time type is a block-pointer type, then that function would in turn be responsible for copying it if it were to outlive its scope. So in this case, you wouldn't need to worry about copying it, without needing to know what the function did.
If, on the other hand, you pass a block pointer as an argument to a function parameter whose declared compile-time type is a non-block object pointer type, then that function wouldn't be taking responsibility for any block copying, because for all it knows it's just a regular object, that just needs to be retained if stored in a place that outlives the current scope. In this case, if you think that the function may possibly store the value beyond the end of the call, you should copy the block before passing it, and pass the copy instead.
By the way, this is also true for any other case where a block-pointer type is assigned or converted to a regular object-pointer type; the block should be copied and the copy assigned, because anyone who gets the regular object-pointer value wouldn't be expected to do any block copying considerations.
ARC complicates the situation somewhat. The ARC specification specifies some situations where blocks are implicitly copied. For example, when storing to a variable of compile-time block-pointer type (or any other place where ARC requires a retain on a value of compile-time block-pointer type), ARC requires that the incoming value be copied instead of retained, so the programmer doesn't have to worry about explicitly copying blocks in those cases.
With the exception of retains done as part of initializing a
__strong parameter variable or reading a __weak variable, whenever
these semantics call for retaining a value of block-pointer type, it
has the effect of a Block_copy.
However, as an exception, the ARC specification does not guarantee that blocks only passed as arguments are copied.
The optimizer may remove such copies when it sees that the result is
used only as an argument to a call.
So whether to explicitly copy blocks passed as arguments to a function is still something the programmer has to consider.
Now, the ARC implementation in recent versions of Apple's Clang compiler has an undocumented feature where it will add implicit block copies to some of the places where blocks are passed as arguments, even though the ARC specification doesn't require it. ("undocumented" because I cannot find any Clang documentation to this effect.) In particular, it appears that it defensively always adds implicit copies when passing an expression of block-pointer type to a parameter of non-block object pointer type. In fact, as demonstrated by CRD, it also adds an implicit copy when converting from a block-pointer type to a regular object-pointer type, so this is the more general behavior (since it includes the argument passing case).
However, it appears that the current version of the Clang compiler does not add implicit copies when passing a value of block-pointer type as varargs. C varargs are not type-safe, and it is impossible for the caller to know what types the function expects. Arguably, if Apple wants to error on the side of safety, since there's no way of knowing what the function expects, they should add implicit copies always in this case too. However, since this whole thing is an undocumented feature anyway, I wouldn't say it's a bug. In my opinion, then programmer should never rely on blocks that are only passed as arguments being implicitly copied in the first place.
Short Answer:
You have found a compiler bug, possibly a re-introduced one, and you should report it at http://bugreport.apple.com.
Longer Answer:
This wasn't always a bug, it used to be a feature ;-) When Apple first introduced blocks they also introduced an optimisation in how they implemented them; however unlike normal compiler optimisations which are essentially transparent to the code they required programmers to sprinkle calls to a special function, block_copy(), in various places to make the optimisation work.
Over the years Apple removed the need for this, but only for programmers using ARC (though they could have done so for MRC users as well), and today the optimisation should be just that and programmers should no longer need to help the compiler along.
But you've just found a case where the compiler gets it wrong.
Technically you have a case a type loss, in this case where something known to be a block is passed as id - reducing the known type information, and in particular type loss involving the second or subsequent argument in a variable argument list. When you look at your array with po tmp you see the first value is correct, the compiler gets that one right despite there being type loss, but it fails on the next argument.
The literal syntax for an array does not rely on variadic functions and the code produced is correct. However initWithObjects: does, and it goes wrong.
Workaround:
If you add a cast to id to the second (and any subsequent) blocks then the compiler produces the correct code:
return [[NSArray alloc] initWithObjects:
^{NSLog(#"blk0:%d", val);},
(id)^{NSLog(#"blk1:%d", val);},
nil];
This appears to be sufficient to wake the compiler up.
HTH

Memory issue when calling dispatch_async with local variable

I am having issues in code when calling dispatch_async. I think that issue is due to ARC reclaiming the object, before it is used in a block, as the method that dispatches it finishes.
- (void) method:(SomeClass *) someClass {
// local variable
NSNumber *someValue = someClass.somePropertyOnManagedObject;
dispatch_async(queue, ^() {
/* call some singleton object passing variable
* when access the variable, reference is nil
*/
[[DashboardFacade sharedInstance] someMethod:someValue];
});
}
After having looking through much documentation, I conclude
Block accesses no parameters – nothing to discuss
Block accesses simple type parameters e.g. BOOL, int - these are copied and not a problem
Block accesses parameter of method that dispatched it - I am not sure, but think
that this is ok
Block accesses property of self – as long as self “lives” until the call has finished ok
Block accesses local variable in method that dispatched it
If we use some semaphores such that we wait for the block to return before leaving the method, then all ok
Otherwise variable may have been garbage collected before block can use.
I think that the solution is to use __block modifier such that ARC retains the variable.
My question is
Is the above technically correct, e.g. using __block will resolve the problem and not introduce other problems?
Why can't I find this anywhere on the internet/google?
Is the above technically correct, e.g. using __block will resolve the
problem and not introduce other problems?
Yes it's technically correct, __block, on ARC, allows you to change the variable (in this case to where its pointing, since it's a NSNumber *), that was declared outside the block context.
Why can't I find this anywhere on the internet/google?
I think the problem is not related to this particular place of your code, but something else.
someValue inside the block can be nil only if it is nil after this assignment:
NSNumber *someValue = someClass.somePropertyOnManagedObject;
Blocks retain objects that are being captured by the blocks as a result of those variables being used inside the blocks. And it doesn’t matter if it is self or a local variable from the scope that is visible to the block.

Is there an Objective-C property attribute that mimics the functionality of the __block keyword?

I want to make a property that allows a block to update its contents. For a typical variable (i.e. not auto-synthesized, etc), I would prefix the declaration with __block.
Is there a way to make a property that is able to be updated by a block?
Edit: Some answers say just to use the properties setter method. What I actually want to do is add objects to a mutable array, so I don't really want to create a new mutable array and set it back to the property using setProperty: or .property = each time. Is it possible to modify the property without all of these memory allocations?
__block is used to declare local variables that a block might want to change.
Neither are properties local variables, nor is there a need to change a variable when all you want to do is add something to a mutable array. The variable does not change, it's the object's state behind the variable that changes.
This isn't the right way to think about it. You want to modify an object, which has a property. So you capture the object in the block, and call its accessors (setFoo:) to modify the property.
EDIT: From the various edits, you may be confusing how ObjC objects work and how C++ works. ObjC only uses pointers to objects, seldom copies them, and lacks the concept of a const object (there are immutable objects, but it's just because they don't have mutators; you can't const a mutable object like you can in C++).
__block just means "this variable (not the object pointed to by it; this actual variable) should be passed by reference into the block rather than by value)." So when I say:
__block id foo;
this means that the foo pointer itself can be changed. It has nothing at all to do with whether the object pointed to by foo can be mutated. This makes no sense for a global or an ivar. ivars are implicitly struct fields. When you say _ivar inside a block, the compiler implicitly converts this to self->_ivar and then captures self. It does not capture _ivar (since that's just an offset into the self struct). It's better to do the same using accessors, since it's much more explicit what you're doing, and you can use __weak that way.
You use __block when you want to modify a variable within a block; in your case what you want to do is not modifying the variable(it will still point to the same NSMutableArray) but just sending a message to it(addObject:). You don't need __block for that.
There is no need to put anything into a #property declaration. since they can be accessed and modified by blocks without any trouble. According to the documentation:
Within the block object’s body of code, variables may be treated in
five different ways.
You can reference three standard types of variable, just as you would
from a function:
Global variables, including static locals
Global functions (which aren’t technically variables)
Local variables and parameters from an enclosing scope
Blocks also support two other types of variable:
At function level are __block variables. These are mutable within the
block (and the enclosing scope) and are preserved if any referencing
block is copied to the heap.
const imports.
The following rules apply to variables used within a block:
Global variables are accessible, including static variables that
exist within the enclosing lexical scope.
Parameters passed to the block are accessible (just like parameters to a function).
Stack (non-static) variables local to the enclosing lexical scope are
captured as const variables.Their values are taken at the point of
the block expression within the program. In nested blocks, the value
is captured from the nearest enclosing scope.
Variables local to the enclosing lexical scope declared with the
__block storage modifier are provided by reference and so are mutable.
Any changes are reflected in the enclosing lexical scope,
including any other blocks defined within the same enclosing lexical
scope.
Local variables declared within the lexical scope of the block,
which behave exactly like local variables in a function.Each
invocation of the block provides a new copy of that variable. These
variables can in turn be used as const or by-reference variables in
blocks enclosed within the block.

Having trouble understanding Objective-C Block Documentation

I'm currently having trouble understanding the fundamentals of Obj-C blocks and the __block storage type. From the following documentation:
http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW6
I'm trying to understand the following paragraph and examples:
When a block is copied, it creates strong references to object variables used within the block. If you use a block within the implementation of a method:
If you access an instance variable by reference, a strong reference is made to self;
If you access an instance variable by value, a strong reference is made to the variable.
The following examples illustrate the two different situations:
dispatch_async(queue, ^{
// instanceVariable is used by reference, a strong reference is made to self
doSomethingWithObject(instanceVariable);
});
id localVariable = instanceVariable;
dispatch_async(queue, ^{
/*
localVariable is used by value, a strong reference is made to localVariable
(and not to self).
*/
doSomethingWithObject(localVariable);
});
To override this behavior for a particular object variable, you can mark it with the __block storage type modifier.
My questions:
How exactly is one example "accessed by reference" while the other one is accessed by variable? Why is localVariable "used by value?"
What does the doc mean by "a strong reference is made to self"? Which "self" is it referring to?
If I add the __block storage type to localVariable in the second example, am I wrong to assume that the block closes over the variable, so it keeps it around in heap until block is released? What other things are happening?
Thank you!
How exactly is one example "accessed by reference" while the other one is accessed by variable? Why is localVariable "used by value?"
One way to understand this is the following:
when you use a local variable in a block defined in the method, what happens is that the content of the variable is copied in some block private memory, so that it is available when the block is executed (after the method exits); in this sense we may talk of accessed "by value" (as in: the value is copied); syntactically the compiler doesn't know what the content of localVariable refers to, so its values is treated as such;
when directly accessing instanceVariable in a block defined within a method of a class, the compiler knows that we are accessing the same object that is executing the method and there is not need to copy anything, since the object has a longer lifetime than the method where the block is found; but we need to ensure that the object is still there when the block is executed, so we get a strong reference to it.
Now, as to the use of "by reference": in the first case, you get a copy of the reference to the class member: if you could change its value (but you can't, because the compiler forbids it), you were just modifying a block private copy, so the original object is not affected.
In the second case, you can modify the value of instanceVariable (like in: it was nil and you allocate an object referred through it) and this will affect the object that executed the method were the block is defined.
What does the doc mean by "a strong reference is made to self"? Which "self" is it referring to?
self is the object which is currently executing the method where the block is found. that a strong reference is made only means (in ARC parlance) that the retain count of the object is incremented (to make sure some other entity cannot cause it to be deallocated by releasing it).
If I add the __block storage type to localVariable in the second example, am I wrong to assume that the block closes over the variable, so it keeps it around in heap until block is released? What other things are happening?
Using __block makes the variable be always accessed "by reference", so you can modify them.
This is how they are handled:
__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 (for example, by being enqueued somewhere for later execution). Multiple blocks in a given lexical scope can simultaneously use a shared variable.
As an optimization, block storage starts out on the stack—just like blocks themselves do. If the block is copied using Block_copy (or in Objective-C when the block is sent a copy), variables are copied to the heap. Thus, the address of a __block variable can change over time.

ios geocodeAddressString modify global variable during block

I understand that the call to CLGeocoder geocodeAddressString is asynchronous, with a block passed in to handle the callback at completion time. I also understand that the only variables that are mutable within the block are local __block variables. But I need to store the resulting CLPlacemarks in a global NSMutableArray variable, and I can't work out how that can happen. Any __block variables can only be accessed within the same method, but at the point that they have any value (i.e. within the block) I can't assign any value to the global array. After the block, the __block variables will likely not have any value because of the immediate return when calling the async geocodeAddressString.
How can I store the results of the call, so that they can be used to update a UITableView?
Ok, solved. I was incorrectly deducing (from my reading about blocks) that properties and instance variables could not be modified within the scope of a block. In my case, the reason I couldn't modify my iVar array was that I hadn't alloc/init'ed it. Once I did that, I was able to assign values and see them outside of the block e.g. in my cellForRowAtIndexPath method of my table view.
Apologies to anyone who may have been misled by my initial assumptions! For the record, I do think that the text on the Apple docs re blocks & variables here is a bit misleading...the only variables that it mentions as being mutable are the __block function-level variables, whereas it says all others "can be accessed" which I took as meaning "read-only" (I know that both getters and setters are accessors, but the context was confusing).

Resources