Block mutates a variable that is indirectly in it's scope - objective-c-blocks

This is the most minimal example I could think of:
#import <Foundation/Foundation.h>
#interface ObjCClass:NSObject
#property void (^aBlockInner) ();
-(void)method;
-initWithBlock:(void (^)())aBlock;
#end
#implementation ObjCClass
- (void)method{
self->_aBlockInner();
}
-(instancetype)initWithBlock:(void (^)())aBlock
{
self->_aBlockInner = aBlock;
return self;
}
#end
struct cppClass{
cppClass(){
objCClassInstance = [[ObjCClass alloc] initWithBlock:^{
modifyY();
}];
[objCClassInstance method];
}
void modifyY() {
y++;
}
int y = 0;
ObjCClass* objCClassInstance;
};
int main()
{
cppClass a{};
NSLog(#"Y is:%d",a.y);
}
The member variable y is supposed to stay untouched as blocks are supposed to copy their “captures”. Though, the final print outputs:
Y is:1
Have I misunderstood Objective-C blocks?
To compile on a macOS do: clang++ main.mm -framework Foundation

Much more minimal example would be as follows:
struct MClass {
int i{};
MClass() {
void(^block)() = ^{
++i;
};
block();
}
};
int main() {
MClass var;
NSLog(#"%d", var.i);
}
This snippet has exactly the same "problem", and i member variable gets changed within a block. This happens, because when you refer to member variables from inside member functions, this implicitly adds this pointer to the expression, so it's not actually i member variable that gets captured, but this pointer which encompasses it. The block above can be equivalently rewritten like this:
void(^block)() = ^{
++this->i;
};
The block makes a copy of the pointer to the same object, not object itself. However, if you had the owning object referred to by value, and not a pointer, you would not be able in fact, alter the object, because the copies a block makes are constant:
struct MClass {
int i{};
};
int main() {
MClass var;
void(^block)() = ^{
// Compile-time error: Read-only variable is not assignable
++var.i;
};
block();
NSLog(#"%d", var.i);
}
And this can only be done with use of the __block modifier:
__block MClass var;
void(^block)() = ^{
++var.i;
};

Related

Objective C: Can a block variable be used only once?

Suppose I have a need for multiple block "calls", for instance a loop in which the block is passed to a another function in each iteration. Do I need to make a new block instance each time I call the function (like Example 1) or can I make one block instance that is called each time (like Example 2)?
//Example 1:
while(true){
void (^block)(NSString* test)=^(NSString* test){
//do something
};
[self callWithBlock: block];
}
//Example 2
void (^block)(NSString* test)=^(NSString* test){
//do something
};
while(true){
[self callWithBlock: block];
}
It compiles and runs fine the second way, but I suspect that any concurrency issues may not be immediately obvious.
You can call blocks as often as you want. But you need to be careful about the context that is captured by the block.
If you have any values that are captured by your block, keep in mind, that unless when specifying them as __block variables, they will be copied.
So for example, this code:
int anInteger = 42;
void (^testBlock)(void) = ^{
NSLog(#"Integer is: %i", anInteger);
};
anInteger = 84;
testBlock();
will print 42, not 84.
If you declare anInteger as __block int anInteger = 42, the storage will be shared and the code will print 84.
So, if you have code that is something like:
int foo = 42;
void (^block)(void) = ^{
NSLog(#"%i", foo);
}
while (true) {
block();
foo++;
}
the behavior will be different from
int foo = 42;
while (true) {
void (^block)(void) = ^{
NSLog(#"%i", foo);
}
block();
foo++;
}
This will also apply to pointers and NSObject variables, when you reassign the variable that holds the pointer or object.
To find out more, have a look at Working with Blocks from the Apple developer documentation.

Is it possible to generate a wrapper for each method invocation in Objective-C?

I have a project with a lot of classes.
I want to log (e.g. to stderr) invocations of each selector in runtime.
My main requirement is not to change the existing code, so I can't just log the function's params at the start of each call.
If some method is invoked during program execution, e.g.
#implementation Class1
// ...
- (int)someFunc:(Class2*) a andClass3:(Class3*)b
{
}
// ...
#end
I want to replace it with something like:
- (int)someFuncWrapper:(Class2*) a andClass3:(Class3*)b
{
NSLog(#"- (int)someFuncWrapper:a andClass3:b <= a=%#, ab=%#", a, b);
return [someFunc: a andClass3:b];
}
Is it possible?
I've read of method swizzling, KVO, forward messaging.
My current approach with method swizzling causes infinite recursion:
- (int)funcToSwizzle:(int)a andB:(int)b
{
int r = a+b;
NSLog(#"funcToSwizzle: %d", r);
return r;
}
- (void)doSimpleSwizzling
{
NSLog(#"r1 = %d", [self funcToSwizzle:10 andB:20]);
Class curClass = NSClassFromString(#"HPTracer");
unsigned int methodCount = 0;
Method *methods = class_copyMethodList( curClass, &methodCount);
for (int i=0; i<methodCount; ++i)
{
SEL originalSelector = method_getName(methods[i]);
if ( strcmp("funcToSwizzle:andB:", sel_getName(originalSelector)) == 0 )
{
Method m1 = class_getInstanceMethod(curClass, originalSelector);
id block3 = ^(id self, int a, int b) {
NSLog(#"My block: %d", a*b);
// get current implementation of "funcToSwizzle".
// copy it. store that "IMP"/"void *" etc
return [self funcToSwizzle:a andB:b];
};
IMP imp3 = imp_implementationWithBlock(block3);
method_setImplementation(m1, imp3);
}
}
NSLog(#"r2 = %d", [self funcToSwizzle:10 andB:20]);
}
And I'm afraid it's impossible to generate a block3 or some method in runtime. There's NSSelectorFromString but no ImplementationFromString.
UPD
I looked at DTrace util, it seems very powerful, but doesn't fit my needs.
It requires disabling SIP on Mac OS, and is either impossible on iOS or possible on jailbreaked device.
What I need from methods interceptions is creating a stable custom "framework" for both Debug and production build modes.

EXC_BAD_ACCESS error when accessing Lua user data in iOS

I am writing an iOS library to embed Lua in games and have encountered a problem regarding userdata. I want users to be able to treat my library objects as normal tables (in Lua scripts) to set attributes and for these attributes to be available to the base objects in the library. For instances a user script may have
line = display.newLine
line.width = 3
Then the width field should be accessible from within the library (Objective C/C) code.
I have this working, sort of, but after running for a few seconds I get an EXC_BAD_ACCESS error, so obviously I am accessing a freed object or have some other type of memory corruption, but I can't seem to figure out why.
I have trimmed down my code to just one example to reproduce the error. First I have a base Objective C object that implements the library functionality. The header is shown below:
#import "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#interface GeminiLine : NSObject {
int selfRef;
int propertyTableRef;
lua_State *L;
}
#property (nonatomic) int propertyTableRef;
-(id)initWithLuaState:(lua_State *)luaStat;
-(double)getDoubleForKey:(const char*) key withDefault:(double)dflt;
#end
This class keeps a reference to the lua_State object and integer Lua references to it's corresponding Lua userdata and uservalue (the tables associated with the userdata). The reference propertyTableRef is used to access the object attributes (uservalue table).
The implementation is given below:
#import "GeminiLine.h"
#implementation GeminiLine
#synthesize propertyTableRef;
-(id)initWithLuaState:(lua_State *)luaState {
self = [super init];
if (self) {
L = luaState;
}
return self;
}
-(double)getDoubleForKey:(const char*) key withDefault:(double)dflt {
lua_rawgeti(L, LUA_REGISTRYINDEX, propertyTableRef);
//lua_pushstring(L, key);
//lua_gettable(L, -2);
lua_getfield(L, -1, key);
if (lua_isnil(L, -1)) {
return dflt;
}
return lua_tonumber(L, -1);
}
-(void)dealloc {
luaL_unref(L, LUA_REGISTRYINDEX, propertyTableRef);
[super dealloc];
}
#end
The only non-lifecycle method here is the getDoubleForKey method, which accesses the Lua uservalue associated with the userdata for the object.
The C code to bind the object to Lua is given here:
///////////// lines ///////////////////////////
static int newLine(lua_State *L){
NSLog(#"Creating new line...");
GeminiLine *line = [[GeminiLine alloc] initWithLuaState:L];
GeminiLine **lLine = (GeminiLine **)lua_newuserdata(L, sizeof(GeminiLine *));
*lLine = line;
[Gemini shared].line = line;
luaL_getmetatable(L, GEMINI_LINE_LUA_KEY);
lua_setmetatable(L, -2);
// append a lua table to this user data to allow the user to store values in it
lua_newtable(L);
lua_pushvalue(L, -1); // make a copy of the table becaue the next line pops the top value
// store a reference to this table so we can access it later
line.propertyTableRef = luaL_ref(L, LUA_REGISTRYINDEX);
// set the table as the user value for the Lua object
lua_setuservalue(L, -2);
NSLog(#"New line created.");
return 1;
}
static int lineGC (lua_State *L){
NSLog(#"lineGC called");
GeminiLine **line = (GeminiLine **)luaL_checkudata(L, 1, GEMINI_LINE_LUA_KEY);
[*line release];
return 0;
}
static int lineIndex( lua_State* L )
{
NSLog(#"Calling lineIndex()");
/* object, key */
/* first check the environment */
lua_getuservalue( L, -2 );
if(lua_isnil(L,-1)){
NSLog(#"user value for user data is nil");
}
lua_pushvalue( L, -2 );
lua_rawget( L, -2 );
if( lua_isnoneornil( L, -1 ) == 0 )
{
return 1;
}
lua_pop( L, 2 );
/* second check the metatable */
lua_getmetatable( L, -2 );
lua_pushvalue( L, -2 );
lua_rawget( L, -2 );
/* nil or otherwise, we return 1 here */
return 1;
}
// this function gets called with the table on the bottom of the stack, the index to assign to next,
// and the value to be assigned on top
static int lineNewIndex( lua_State* L )
{
NSLog(#"Calling lineNewIndex()");
int top = lua_gettop(L);
NSLog(#"stack has %d values", top);
lua_getuservalue( L, -3 );
/* object, key, value */
lua_pushvalue(L, -3);
lua_pushvalue(L,-3);
lua_rawset( L, -3 );
NSLog(#"Finished lineNewIndex()");
return 0;
}
// the mappings for the library functions
static const struct luaL_Reg displayLib_f [] = {
{"newLine", newLine},
{NULL, NULL}
};
// mappings for the line methods
static const struct luaL_Reg line_m [] = {
{"__gc", lineGC},
{"__index", lineIndex},
{"__newindex", lineNewIndex},
{NULL, NULL}
};
int luaopen_display_lib (lua_State *L){
// create meta tables for our various types /////////
// lines
luaL_newmetatable(L, GEMINI_LINE_LUA_KEY);
lua_pushvalue(L, -1);
luaL_setfuncs(L, line_m, 0);
/////// finished with metatables ///////////
// create the table for this library and popuplate it with our functions
luaL_newlib(L, displayLib_f);
return 1;
}
The key methods here are newLine and lineNewIndex. In newLine I create the objective C GeminiLine object corresponding to the Lua object and store a pointer to it in Lua userdata. I also store a pointer to the new object in a singleton Gemini object, which is the object that provides the main program with access to executing Lua scripts. This class is given here:
Gemini *singleton = nil;
#interface Gemini () {
#private
lua_State *L;
}
#end
#implementation Gemini
#synthesize line;
- (id)init
{
self = [super init];
if (self) {
L = luaL_newstate();
luaL_openlibs(L);
}
return self;
}
+(Gemini *)shared {
if (singleton == nil) {
singleton = [[Gemini alloc] init];
}
return singleton;
}
-(void)execute:(NSString *)filename {
int err;
lua_settop(L, 0);
NSString *luaFilePath = [[NSBundle mainBundle] pathForResource:filename ofType:#"lua"];
setLuaPath(L, [luaFilePath stringByDeletingLastPathComponent]);
err = luaL_loadfile(L, [luaFilePath cStringUsingEncoding:[NSString defaultCStringEncoding]]);
if (0 != err) {
luaL_error(L, "cannot compile lua file: %s",
lua_tostring(L, -1));
return;
}
err = lua_pcall(L, 0, 0, 0);
if (0 != err) {
luaL_error(L, "cannot run lua file: %s",
lua_tostring(L, -1));
return;
}
}
#end
For my test program I have created an application using the single view template. I modified the applicationDidFinishLaunching method on the AppDelegate to call a test script as follows:
-(void) update {
double width = [[Gemini shared].line getDoubleForKey:"width" withDefault:5.0];
NSLog(#"width = %f", width);
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
[[Gemini shared] execute:#"test"];
timer = [NSTimer scheduledTimerWithTimeInterval:0.01
target:self
selector:#selector(update)
userInfo:nil
repeats:YES];
....
I have also included a timer that fires 100 times per second and an update method as its target. The update method retrieves the attribute set in the lua script, width, and logs it with NSLog.
The test.lua script I am using is given below:
display = require('display')
line = display.newLine()
line.width = 3;
Now when I run this code, it executes correctly for several seconds, printing out the correct message and appropriate line width, but then it fails with an EXC_BAD_ACCESS error on the NSLog(#"width = %f", width); line of the update method. At first I thought maybe the line object was being garbage collected, but the lineGC method would log this and it does not. So I'm convinced the problem is in the way I am using the uservalue of my Lua userdata, either in setup or access.
Can anyone see an error in the way I have implemented this?
EDIT
To confirm that my userdata isn't being garbage collected, I disabled the GC before even loading the script using lua_gc(L, LUA_GCSTOP, 0);. Still get exactly the same problem.
I forgot to mention earlier that I'm using Lua 5.2.
Turning on every memory debugging flag using "Edit scheme" indicates that the error is happening in the following Lua code base function on the call to setsvalue2s, which is actually a macro:
LUA_API void lua_getfield (lua_State *L, int idx, const char *k) {
StkId t;
lua_lock(L);
t = index2addr(L, idx);
api_checkvalidindex(L, t);
setsvalue2s(L, L->top, luaS_new(L, k));
api_incr_top(L);
luaV_gettable(L, t, L->top - 1, L->top - 1);
lua_unlock(L);
}
I've run into similar issues. My guess, is that the Lua memory manager (or ObjC manager) is releasing the object. It works correctly for a few seconds because it will not have been garbage collected.
I'm pretty sure I have the answer to my own question now. The problem is in the getDoubleForKey method:
-(double)getDoubleForKey:(const char*) key withDefault:(double)dflt {
lua_rawgeti(L, LUA_REGISTRYINDEX, propertyTableRef);
//lua_pushstring(L, key);
//lua_gettable(L, -2);
lua_getfield(L, -1, key);
if (lua_isnil(L, -1)) {
return dflt;
}
return lua_tonumber(L, -1);
}
I'm new to Lua and had not realized that I needed to empty the stack after making calls like this. When my library functions are invoked by Lua there is no need, but here I am making the call so Lua does not bail me out.
I found this out by printing out the stack size at the top of the method and seeing it increasing with every call. Eventually the stack got so big that bad things happened. The solution is to empty out the stack before exiting the method:
-(double)getDoubleForKey:(const char*) key withDefault:(double)dflt {
lua_rawgeti(L, LUA_REGISTRYINDEX, propertyTableRef);
lua_getfield(L, -1, key);
if (lua_isnil(L, -1)) {
lua_pop(L,2);
return dflt;
}
double rval = lua_tonumber(L, -1);
lua_pop(L, 2);
return rval;
}

Checking Objective-C block type?

This is primarily a curiosity, I'm not really sure what's the practical use of this but here goes.
Since blocks are also Objective-C objects, is it possible to check their type? That is, does it respond to the isKindOfClass: message and how to use that message with respect to blocks?
My naive thought that it's probably like this:
-(void) aMethod {
typedef int (^BlockA)(int x, int y);
id blockVar = ...; // get a block from somewhere
if([blockVar isKindOfClass:BlockA]) {
BlockA blockVarA = blockVar;
int result = blockVarA(1,2);
}
}
The code above probably won't work. But if it is possible to check a block's type, what is the correct way to do it?
Can do, kinda sorta.
But first, let's disambiguate. -[NSObject isKindOfClass:] can tell you it's a block, and that's about it. E.g. I believe this line of code -- ostensibly & unfortunately A BAD IDEA -- will return YES for blocks on present Lion & iOS 5.x:
[myBlock isKindOfClass:NSClassFromString(#"NSBlock")]
That won't help you distinguish the block's function signature.
But it can be done, by snagging the signature from the block's documented internal struct. Code follows for an example OS X command-line app, much of which ripped from Mike Ash's MABlockClosure (great detailed explanation). (UPDATE: Github project CTObjectiveCRuntimeAdditions also apparently provides library code for just this purpose.)
#import <Foundation/Foundation.h>
struct BlockDescriptor {
unsigned long reserved;
unsigned long size;
void *rest[1];
};
struct Block {
void *isa;
int flags;
int reserved;
void *invoke;
struct BlockDescriptor *descriptor;
};
static const char *BlockSig(id blockObj)
{
struct Block *block = (void *)blockObj;
struct BlockDescriptor *descriptor = block->descriptor;
int copyDisposeFlag = 1 << 25;
int signatureFlag = 1 << 30;
assert(block->flags & signatureFlag);
int index = 0;
if(block->flags & copyDisposeFlag)
index += 2;
return descriptor->rest[index];
}
int main(int argc, const char * argv[])
{
#autoreleasepool {
int (^block)(NSNumber *) = ^(NSNumber *num) {
NSLog(#"%# %#", NSStringFromClass([num class]), num);
return [num intValue];
};
NSLog(#"signature %s", BlockSig(block));
NSLog(#"retval %d", (int)block([NSNumber numberWithInt:42]));
}
return 0;
}
Run this and you should get something like:
[58003:403] signature i16#?0#8
[58003:403] __NSCFNumber 42
[58003:403] retval 42
The numbers in the signature (I'm told they are offsets) can be stripped for simpler i#?#.
The signature is in the #encode format, which isn't perfect (e.g. most objects map to same #), but should afford you some ability to distinguish blocks with different signatures at runtime.
While it's not documented in the Apple link, my testing points to #? being the code for a block type, which makes sense of the signature above. I found a clang-developers discussion on this issue which seems to back this up.
The "BlockA" in (^BlockA) is the variable name (in this case a typedef), not its class.
Blocks are objects, but not regular subclasses of NSObject. They only implement a subset of the methods. -isKindOfClass: will probably just crash.
Blocks are of the type NSMallocBlock or NSConcreteGlobalBlock, ... depending on where they were created (heap, stack, ...).
It seems that blocks are of classes like __NSGlobalBlock__, __NSStackBlock__, or __NSMallocBlock__, etc., whose inheritance chain eventually goes to NSBlock and then NSObject. So you could test whether something is a block by doing [... isKindOfClass:NSClassFromString(#"NSBlock")]. However, there doesn't seem to be any way to query a block's signature (return type and argument types) at runtime, so you wouldn't be able to distinguish between blocks of different signatures.
As well as Apple having nothing I can find to say on the matter, poking at a block with class_copyMethodList and method_getName reveals no obvious exposed methods. So I'm going to say that it isn't possible to check their type.
A old question, but anyway:
If you want a simple way of doing this: (Compile it with -fno-objc-arc)
Class __NSGlobalBlock__CLASS () {
static Class result = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
dispatch_block_t thisIsAGlobalBlock = ^{// a block with no variables will be a __NSGlobalBlock__
};
result = [[thisIsAGlobalBlock class] retain];
});
return result;
};
Class __NSStackBlock__CLASS () {
static Class result = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
__block dispatch_block_t thisIsAStackBlock = ^{
return ;// we really DON'T want infinate recursion
thisIsAStackBlock();// including a reference to __block var makes this a __NSStackBlock__
};
result = [[thisIsAStackBlock class] retain];
});
return result;
};
Class __NSMallocBlock__CLASS () {
static Class result = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
__block dispatch_block_t thisIsAMallocBlock = Block_copy(// << turns the __NSStackBlock__ Block into a __NSMallocBlock__
^{
return ;// we really DON'T want infinate recursion
thisIsAMallocBlock();// including a reference to __block var makes this a __NSStackBlock__
});
result = [[thisIsAMallocBlock class] retain];
Block_release(thisIsAMallocBlock);
});
return result;
};
Test Code:
#autoreleasepool {
__block dispatch_block_t iAmAGlobalBlock = ^{
};
__block dispatch_block_t iAmAStackBlock = ^{
return;
iAmAStackBlock();
};
dispatch_block_t iAmHeapBlock = Block_copy(iAmAStackBlock);
dispatch_block_t iAmNotAHeapBlock = Block_copy(iAmAGlobalBlock);
if ([iAmAGlobalBlock isKindOfClass:__NSGlobalBlock__CLASS()]) {
NSLog(#"very great success!");
}
if ([iAmAStackBlock isKindOfClass:__NSStackBlock__CLASS()]) {
NSLog(#"another great success!");
}
if ([iAmHeapBlock isKindOfClass:__NSMallocBlock__CLASS()]) {
NSLog(#"also great success!");
}
if ([iAmNotAHeapBlock isKindOfClass:__NSGlobalBlock__CLASS()]) {
NSLog(#"yet another great success!");
}
NSLog (#"Block classes, as reported by NSStringFromClass():\n__NSGlobalBlock__CLASS() = %#\n__NSStackBlock__CLASS() = %#\n__NSMallocBlock__CLASS() = %#\n[iAmAGlobalBlock class] = %#\n[iAmAStackBlock class] = %#\n[iAmHeapBlock class] = %#\n[iAmNotAHeapBlock class] = %#\n",
NSStringFromClass(__NSGlobalBlock__CLASS()),
NSStringFromClass(__NSStackBlock__CLASS()),
NSStringFromClass(__NSMallocBlock__CLASS()),
NSStringFromClass([iAmAGlobalBlock class]),
NSStringFromClass([iAmAStackBlock class]),
NSStringFromClass([iAmHeapBlock class]),
NSStringFromClass([iAmNotAHeapBlock class])
);
Block_release(iAmHeapBlock);
Block_release(iAmNotAHeapBlock);// not really needed, but since we did "Block_copy" it...
}

Function that returns a function

How to assign and subsequently call a function that returns a function to a local variable in Objective-C?
UPDATE:
I've come up with the following but it's still not right I'm afraid:
(void (^)()) (^loadedCallback) () = (void (^)()) ^(){
#synchronized (synchronizer) {
semaphore++;
}
return Block_copy(^{
#synchronized (synchronizer) {
semaphore--;
if (semaphore == 0) {
onAllLoaded();
}
}
}); };
First, you need to understand the function pointer declaration syntax. It's the same for blocks, except that it's a ^ instead of a *.
Then, you need to create a block and return a copy of it, and assign that to a correctly-declared variable.
typedef NSArray* (^my_block_type_t)(int, float);
my_block_type_t createBlock()
{
my_block_type_t block = ^(int a, float b)
{
return [NSArray array];
};
return Block_copy(block);
}
/* snip */
my_block_type_t theBlock = createBlock();
theBlock();
Block_release(theBlock);
EDIT to address OP's edit: typedefs are typically used to make code easier to read. In the case of blocks and function pointers, it also makes it easier to write. There is a built-in typedef (dispatch_block_t) for blocks that accept no arguments and return void; you should use it. You should also make as many typedefs as you need to avoid having to use the ugly declaration syntax function pointers otherwise force onto your code.
typedef dispatch_block_t (^block_creator_t)();
block_creator_t loadedCallback = ^{
#synchronized (synchronizer)
{
semaphore++;
}
dispatch_block_t result = ^{
#synchronized (synchronizer)
{
semaphore--;
if (semaphore == 0)
onAllLoaded();
}
};
return Block_copy(result);
};