Reputation: 1513
Are they the same, copy
and Block_copy()
? How? or if not, what are the differences?
I was curious about this for a while so I decided to do some researches.
See what I found it my answer.
Upvotes: 3
Views: 471
Reputation: 122518
When used on an expression of block pointer type, the method copy
and the function Block_copy()
are the same. And likewise the method release
and the function Block_release()
are the same. The methods copy
and release
are just more Objective-C messaging style, since blocks are objects in Objective-C, and are memory managed using retain
and release
like other Cocoa objects. On the other hand, when used in C/C++, blocks can only be managed with Block_copy()
and Block_release()
.
Upvotes: 0
Reputation: 1513
Finally, I found the answer. copy
and Block_copy()
are the same, but not that exactly.
Here is what I found :
Let's take a look at the classes of blocks, there are 3 of them :
__NSGlobalBlock__
- You will get a block of this class if you implement a block without any references to the outside of the block.
void(^block)() = ^{ NSLog(@"GRAZZZZ"); };
__NSStackBlock__
- You will get a block of this class if you implement a block with one or more references to the outside of the block, (you will get this when you are running on non-ARC environment only. In ARC env, ARC copies it for you automatically).
// NON-ARC CODE
int theOutsider = 1234;
void(^block)() = ^{ NSLog(@"%d", theOutsider); };
__NSMallocBlock__
- You will get a block of this class if you copy a __NSStackBlock__
block.
int theOutsider = 1234;
void(^block1)() = [^{ NSLog(@"%d", theOutsider); } copy]; // NON-ARC VERSION
void(^block2)() = ^{ NSLog(@"%d", theOutsider); }; // ARC VERSION
For __NSGlobalBlock__
, when you call copy
to it, it does nothing, just return. So, just ignore it. There is no need to move anything to heap. Below is the assembly of -[__NSGlobalBlock copy]
(its super class) :
CoreFoundation`-[__NSGlobalBlock copy]:
0x7fff8bd016f0: pushq %rbp
0x7fff8bd016f1: movq %rsp, %rbp
0x7fff8bd016f4: movq %rdi, %rax
0x7fff8bd016f7: popq %rbp
0x7fff8bd016f8: ret
0x7fff8bd016f9: nopl (%rax)
For __NSStackBlock__
and __NSMallocBlock__
, when you call copy
to them, they forward to copy
method of its super class, -[NSBlock copy]
. Here is its assembly code on OS X 10.9 SDK :
CoreFoundation`-[NSBlock copy]:
0x7fff8bcc86a0: pushq %rbp
0x7fff8bcc86a1: movq %rsp, %rbp
0x7fff8bcc86a4: pushq %rbx
0x7fff8bcc86a5: pushq %rax
0x7fff8bcc86a6: movq %rdi, %rbx
0x7fff8bcc86a9: callq 0x7fff8be360ac ; symbol stub for: objc_collectingEnabled
0x7fff8bcc86ae: movq %rbx, %rdi
0x7fff8bcc86b1: addq $0x8, %rsp
0x7fff8bcc86b5: testb %al, %al
0x7fff8bcc86b7: je 0x7fff8bcc86c0 ; -[NSBlock copy] + 32
0x7fff8bcc86b9: popq %rbx
0x7fff8bcc86ba: popq %rbp
0x7fff8bcc86bb: jmpq 0x7fff8be361f6 ; symbol stub for: _Block_copy_collectable
0x7fff8bcc86c0: popq %rbx
0x7fff8bcc86c1: popq %rbp
0x7fff8bcc86c2: jmpq 0x7fff8be361f0 ; symbol stub for: _Block_copy
0x7fff8bcc86c7: nopw (%rax,%rax)
The assembly code on iOS 7.1 SDK :
CoreFoundation`-[NSBlock copy]:
0x17949d0: pushl %ebp
0x17949d1: movl %esp, %ebp
0x17949d3: popl %ebp
0x17949d4: jmp 0x18d3d8a ; symbol stub for: _Block_copy
0x17949d9: nopl (%eax)
As you can see in the code, -[NSBlock copy]
does call _Block_copy
!.
Enough for copy
, let's take a look at Block_copy()
. It is defined in Block.h
as this :
#define Block_copy(...) ((__typeof(__VA_ARGS__))_Block_copy((const void *)(__VA_ARGS__)))
Block_copy()
does call _Block_copy
too!!
To this point, I can summarise that copy
and Block_copy()
are the same!.
Hope this can help someone with the same curiosity as me :D.
Upvotes: 5