Objective-C Blocks, Recursion Fails - objective-c

Sup guys,
I'm trying to do a function that calls itself but by putting everything on one block,
As you can see, the following function is intended to be called an indefinite amount of times (until arcrandom returns a number lower than 50) and you should expect as an output a variable number of "RUNNING" messages, depending on chance.
void (^_test_closure)(void) = ^ {
NSLog(#"RUNNING");
if(arc4random() % 100 > 50) {
_test_closure();
}
};
_test_closure();
However, when running it, I get an EXC_BAD_ACCESS error and the reason I've found is that when the code tries to calls _test_closure inside of the closure it basically points to nowhere.
Does anyone know how to make the above code work?

You have to declare your block itself as a block variable:
__block void (^_test_closure)();
_test_closure = ^{
NSLog(#"Running...");
if ((arc4random() % 100) > 50) {
_test_closure();
}
}
_test_closure();

Recursion and blocks is tricky. Because a block captures all variables passed in, the variable _test_closure is not initialized yet (and clang should give you a warning:
Block pointer variable '_test_closure' is uninitialized when captured by block
).
There are several ways you can get around this, but the most obvious & simplest is to just make the block itself a __block variable (what #H2CO3 said). This allows the block to be weak-linked almost, so that when you call it again, it is properly initialized.
Another option you have is making the block a global or static, like this:
// outside of 'main', thus being a global variable
void (^blockRecurse)(int) = ^(int level) {
if (level < 0)
return;
NSLog(#"Level: %i", level);
blockRecurse(--level);
};
int main()
{
#autoreleasepool {
blockRecurse(10);
}
}
This means it's not being captured by the block, but instead it's referencing the global / static variable, which can be changed by all code equally.

It works with XCode 5 - no warnings, no retain cycles:
typedef void(^blockT)();
blockT block1;
blockT __block block1recursive;
block1recursive = block1 = ^(){
block1recursive();
};
block1();

Related

C++/CLI pin_ptr's usage in proper way

I am newbie of C++/CLI.
I already know that the pin_ptr's functionality is making GC not to learn to specified object.
now let me show you msdn's example.
https://msdn.microsoft.com/en-us//library/1dz8byfh.aspx
// pin_ptr_1.cpp
// compile with: /clr
using namespace System;
#define SIZE 10
#pragma unmanaged
// native function that initializes an array
void native_function(int* p) {
for(int i = 0 ; i < 10 ; i++)
p[i] = i;
}
#pragma managed
public ref class A {
private:
array<int>^ arr; // CLR integer array
public:
A() {
arr = gcnew array<int>(SIZE);
}
void load() {
pin_ptr<int> p = &arr[0]; // pin pointer to first element in arr
int* np = p; // pointer to the first element in arr
native_function(np); // pass pointer to native function
}
int sum() {
int total = 0;
for (int i = 0 ; i < SIZE ; i++)
total += arr[i];
return total;
}
};
int main() {
A^ a = gcnew A;
a->load(); // initialize managed array using the native function
Console::WriteLine(a->sum());
}
hear is the question.
Isn't it okay, the passed object(arr) not pinned ?
because the unmanaged code(native_function) is sync operation and finished before the C++/CLI code (load)
is there any chance the gc destory arr, even though the main logic is running?
(I think A is main's stack variable and arr is A's member variable, so while running main, it should visible)
if so, how can we guarantee that the A is there before invoking load?
(only while not running in native-code?)
int main() {
A^ a = gcnew A;
// I Think A or arr can be destroyed in here, if it is able to be destroyed in native_function.
a->load();
...
}
Thanks, in advance.
The problem that is solved by pinning a pointer is not a normal concurrency issue. It might be true that no other thread will preempt the execution of your native function. However, you have to count in the garbage collector, which might kick in whenever the .NET runtime sees fit. For instance, the system might run low on memory, so the runtime decides to collect disposed objects. This might happen while your native function executes, and the garbage collector might relocate the array it is using, so the pointer you passed in isn't valid anymore.
The golden rule of thumb is to pin ALL array pointers and ALL string pointers before passing them to a native function. ALWAYS. Don't think about it, just do it as a rule. Your code might work fine for a long time without pinning, but one day bad luck will strike you just when it's most annoying.

Why can setting a Block variable inside an if statement cause a carsh?

I found an block example in the book "Effective Objective-C 2.0"
void (^block)();
if (/* some condition */) {
block = ^ {
NSLog(#"Block A");
};
} else {
block = ^ {
NSLog(#"Block B");
};
}
block();
The code is dangerous, and here is the explanation in the book:
The two blocks that are defined within the if and else statements are allocated within stack memory. When it allocates stack memory for each block, the compiler is free to overwrite this memory at the end of the scope in which that memory was allocated. So each block is guaranteed to be valid only within its respective if-statement section. The code would compile without error but at runtime may or may not function correctly. If it didn’t decide to produce code that overwrote the chosen block, the code would run without error, but if it did, a crash would certainly occur.
I don't understand the meaning of "If it didn’t decide to produce code that overwrote the chosen block, the code would run without error, but if it did, a crash would certainly occur."
Can someone explain and give examples?
The issue is similar to that of a C array being created locally to a function and then used after the function returns:
#import <Foundation/Foundation.h>
dispatch_block_t global_block;
int * global_arr;
void set_globals(void)
{
if( YES ){
global_block = ^{
NSLog(#"Summer is butter on your chin and corn mush between every tooth.");
};
int arr[5] = {1, 2, 3, 4, 5};
global_arr = arr;
}
}
void write_on_the_stack(int i)
{
int arr[5] = {64, 128, 256, 512, 1024};
int v = arr[3];
dispatch_block_t b = ^{
int j = i + 10;
j += v;
};
b();
}
int main(int argc, const char * argv[])
{
#autoreleasepool {
set_globals();
write_on_the_stack();
global_block();
NSLog(#"%d", global_arr[0]); // Prints garbage
}
return 0;
}
The space on the stack that was used to store the values of the array may be re-used for any purpose. I use the separate function here because it most reliably demonstrates the problem. For your exact case, with the if block and the access in the same function, the compiler is still free to re-use the stack space. It may not, but you can't rely on that. You're breaking the scope rules of the language (derived from C).
As Jesse Rusak and CrimsonChris pointed out in comments, though, with a Block-type variable compiled under ARC, the Block is created on the stack like the array, but copied off the stack (to the heap) when it's stored in a strong pointer. All object pointers, including your global, are strong by default.
If you were not compiling with ARC, this would be unreliable. I can't come up with a failing example with my current compiler, but again, it's breaking the rules and the compiler is under no obligation to do what you want.
Essentially what this is saying is that if there's code running on a separate thread, and something gets assigned to the area of memory currently used by block but before the block() call, then bad things will happen.
void (^block)();
if (/* some condition *)) {
block = ^ {
NSLog(#"Block A");
}
} else {
block = ^ {
NSLog(#"Block B");
}
}
<--- another thread overwrites the **block** block
block(); <--- runtime error since **block** has been dereferenced.

Can you append code to an Objective-C block variable?

I want to dynamically add code to a block variable, or merge or concatenate a block with another block. Is this possible?
One way of doing it is creating a block that calls the block to be "expanded" before performing its own functions.
For example, consider the example below that adds logging functionality to an arbitrary block passed into it:
typedef void (^MyBlock)(int);
-(MyBlock) expand:(MyBlock)nested {
return ^(int x) {
nested(x);
NSLog("The value of x = %d", x);
};
}
The cumulative effect of calling the block produced by expand: is that of invoking the original block, followed by an operation from the expanded block. You can take it further, to create an appendBlock method:
-(MyBlock) appendBlock:(MyBlock)second toBlock:(MyBlock)first {
return ^(int x) {
first(x);
second(x);
};
}
Is this possible?
No, but you can create a collection of blocks and execute them sequentially.
Sure - just create a new block, which makes use of the original in whatever compositional way you'd like. If you've got block1 and block2, you might create:
someCodeBefore = ^myBlockType(block1) {
someCode()
thatIWantBefore();
block1();
}
someCodeAfter = ^myBlockType(block1) {
block1();
someCode()
thatIWantAfterBlock1();
}
composedBlocks = ^myBlockType(block1, block2) {
block1();
block2();
}
Just make sure you're copying the blocks correctly.

How to enforce parameters of anonymous blocks to be unused in Objective-C?

I've run into a situation while using a library called TransitionKit (helps you write state machines) where I am want to supply entry and exit actions in the form of a callback.
Sadly, the callbacks include two completely useless parameters. A typical block has to look like this:
^void (TKState *state, TKStateMachine *stateMachine) {
// I TOTALLY don't want parameters `state` or `stateMachine` used here
};
(this is an anonymous code block. Read up on blocks here if you're unclear)
As I've noted in the comment, I really don't want those parameters even mentioned in the body there. I've tried simply removing the parameter names like suggested in this question like so:
^void (TKState *, TKStateMachine *) {
// I foobar all I like here
};
but sadly the code won't compile then :(.
How can I enforce this non-usage of parameters in code?
This is what I could come up with. Quite a hack and relies on the GCC poison pragma, which is not standard but a GNU extension - although, given that you are probably compiling this with clang anyway, it should not be a problem.
#define _state state
#define _stateMachine stateMachine
#pragma GCC poison state stateMachine
Then this compiles:
^(TKState *_state, TKStateMachine *_stateMachine) {
do_something();
}
But this doesn't:
^(TKState *_state, TKStateMachine *_stateMachine) {
do_something(state, stateMachine);
}
You could just have a function that took one kind of block, and returned another, like this:
#class TKState, TKStateMachine; // here so this will compile
typedef void (^LongStateBlock)(TKState *state, TKStateMachine *stateMachine);
static inline LongStateBlock Adapter(void(^block)()) {
void(^heapBlock)() = [block copy]; // forces block to be on heap rather than stack, a one-time expense
LongStateBlock longBlock = ^(TKState *s __unused, TKStateMachine *sm __unused) {
heapBlock();
};
// this is the non-ARC, MRR version; I'll leave ARC for the interested observer
[heapBlock release];
return [[longBlock copy] autorelease];
}
And in practice:
// this represents a library method
- (void)takesLongStateBlock:(LongStateBlock)longBlock
{
// which hopefully wouldn't look exactly like this
if (longBlock) longBlock(nil, nil);
}
- (void)yourRandomMethod
{
[self takesLongStateBlock:^(TKState *state, TKStateMachine *stateMachine) {
NSLog(#"Gratuitous parameters, AAAAHHHH!");
}];
[self takesLongStateBlock:Adapter(^{
NSLog(#"So, so clean.");
})];
}
The whole thing is gisted, and should compile inside any class. It does what you expect when you call -yourRandomMethod.
AFAIK there is no way to do what you want when you are creating a block, you can only miss the parameter names when you are declaring a block variable(a reference to a block, to avoid misunderstandings)
So here you can miss the param names:
void (^myBlock)(SomeClass *);
But not when you create a block:
myBlock = ^(SomeClass *o)
{
};
I'd write
^void (TKState *unused_state, TKStateMachine *unused_stateMachine) {
// Anyone using unused_state or unused_stateMachine gets what they deserve.
};
Of course someone can use the parameters. But then whatever you do, they can change the code. If someone is intent on shooting themselves in the foot, there is no stopping them.

Don't understand example given of block scope

In the Apple block documentation is an example of code not to write:
void dontDoThisEither() {
void (^block) (void);
int i = random();
if (i > 1000) {
block = ^{printf("got i at: %d\n", i); };
}
// ...
}
The comments for the code say the block literal scope is the "then" clause.
I don't understand what they mean by that, there is no then clause, which is presumably why they have put it in quotes. But why have they put it in quotes and what is the relationship to the block's scope?
Think of an if statement as:
if this then that else this other thing
The {... block = ...} is in the then that part of the if statement. That is, it is *a sub-scope of the scope of the dontDoThisEither() function.
Because blocks are created on the stack and are only valid within the scope of their declaration, that means that the block assignment in that example is only valid within the then that scope of the if statement.
I.e. Consider:
void dontDoThisEither() {
void (^block) (void);
int i = random();
if (i > 1000) {
block = ^{printf("got i at: %d\n", i); };
} else {
block = ^{printf("your number is weak and small. ignored.\n");};
}
block();
}
At the time block(); is executed the block that it is pointing to is in a scope that is no longer valid and the behavior will be undefined (and likely crashy in a real world example).