@autorelease Pool and loops (for, while, do) Syntax

clang allows the following loop syntax:

 for (...) @autorelease { ... } while (...) @autorelease { ... } do @autorelease { ... } while (...); 

I have not yet found any documentation on this syntax (Apple does not use this syntax in its manuals, at least not in the manuals representing the @autorelease construct), but is it reasonable to assume that the three above are equivalent to the following statements:

 for (...) { @autorelease { ... } } while (...) { @autorelease { ... } } do { @autorelease { ... } } while (...); 

Since this is what I would expect from them (adhering to standard C syntax rules), I'm still not quite sure if this is true. It could also be some β€œspecial syntax” where the autoresource pool is not updated for each iteration of the loop.

+4
source share
4 answers

Both syntaxes are the same

 -(void)aFunc { int i=0; for(;i<5;) @autoreleasepool { ++i; } } -(void)bFunc { int i=0; for(;i<5;) { @autoreleasepool { ++i; } } } 

Build code

  "-[AppDelegate aFunc]": ## @"\01-[AppDelegate aFunc]" .cfi_startproc Lfunc_begin0: .loc 1 12 0 ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:12:0 ## BB#0: pushq %rbp Ltmp2: .cfi_def_cfa_offset 16 Ltmp3: .cfi_offset %rbp, -16 movq %rsp, %rbp Ltmp4: .cfi_def_cfa_register %rbp subq $32, %rsp movq %rdi, -8(%rbp) movq %rsi, -16(%rbp) .loc 1 14 12 prologue_end ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:14:12 Ltmp5: movl $0, -20(%rbp) LBB0_1: ## =>This Inner Loop Header: Depth=1 .loc 1 15 5 ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:15:5 Ltmp6: cmpl $5, -20(%rbp) jge LBB0_3 ## BB#2: ## in Loop: Header=BB0_1 Depth=1 .loc 1 16 26 ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:16:26 Ltmp7: callq _objc_autoreleasePoolPush .loc 1 17 13 ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:17:13 movl -20(%rbp), %ecx addl $1, %ecx movl %ecx, -20(%rbp) .loc 1 18 9 ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:18:9 movq %rax, %rdi callq _objc_autoreleasePoolPop jmp LBB0_1 Ltmp8: LBB0_3: .loc 1 19 1 ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:19:1 addq $32, %rsp popq %rbp ret Ltmp9: Lfunc_end0: .file 2 "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObject.h" .file 3 "/Users/Parag/Desktop/Test/Test/AppDelegate.h" .cfi_endproc .align 4, 0x90 "-[AppDelegate bFunc]": ## @"\01-[AppDelegate bFunc]" .cfi_startproc Lfunc_begin1: .loc 1 20 0 ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:20:0 ## BB#0: pushq %rbp Ltmp12: .cfi_def_cfa_offset 16 Ltmp13: .cfi_offset %rbp, -16 movq %rsp, %rbp Ltmp14: .cfi_def_cfa_register %rbp subq $32, %rsp movq %rdi, -8(%rbp) movq %rsi, -16(%rbp) .loc 1 22 12 prologue_end ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:22:12 Ltmp15: movl $0, -20(%rbp) LBB1_1: ## =>This Inner Loop Header: Depth=1 .loc 1 23 5 ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:23:5 Ltmp16: cmpl $5, -20(%rbp) jge LBB1_3 ## BB#2: ## in Loop: Header=BB1_1 Depth=1 .loc 1 25 26 ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:25:26 Ltmp17: callq _objc_autoreleasePoolPush .loc 1 26 14 ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:26:14 movl -20(%rbp), %ecx addl $1, %ecx movl %ecx, -20(%rbp) .loc 1 27 9 ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:27:9 movq %rax, %rdi callq _objc_autoreleasePoolPop Ltmp18: .loc 1 28 5 ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:28:5 jmp LBB1_1 Ltmp19: LBB1_3: .loc 1 29 1 ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:29:1 addq $32, %rsp popq %rbp ret Ltmp20: Lfunc_end1: 
+7
source

The reason the first syntax example works is understandable if you think that any conditional statement can omit the { ... } block, as a result of which only the next statement is executed.

For instance:

 if (something == YES) NSLog(@"Something is yes"); 

equivalently

 if (something == YES) { NSLog(@"Something is yes"); } 

The @autoreleasepool { ... } block is simply the next statement following the conditional expression.

Personally, I use the second syntax, because it is less prone to errors when making changes, and it becomes easier for me to read. Imagine that when you add an expression between the conditional and the @autoreleasepool { ... } block, the result is significantly different from the original. See This Naive Example ...

 int i = 1; while (i <= 10) @autoreleasepool { NSLog(@"Iteration %d", i); ++i; } 

Print "Iteration 1" through "Iteration 10". But:

 int i = 1; int total = 0; while (i <= 10) total += i; @autoreleasepool { NSLog(@"Iteration %d", i); ++i; } 

Actually it will cause an infinite loop because the ++i operator will never be reached, since it is syntactically equivalent:

 int i = 1; int total = 0; while (i <= 10) { total += i; } @autoreleasepool { NSLog(@"Iteration %d", i); ++i; } 
+8
source

I tried the following code:

 @interface Foo : NSObject @end @implementation Foo - (void) dealloc { NSLog(@"Deallocating %@.", self); [super dealloc]; } @end for (;;) @autoreleasepool { [[[Foo alloc] init] autorelease]; sleep(1); } 

The console begins to populate with freed instances of Foo , so the syntax works as expected.

+1
source

This is just the usual C syntax for blocks and statements. If if , else , for , while , etc. They do not have curly braces; they accept the following statement, which can be a compound statement.

For example, you can:

 for (...) if (...) { ... } if (...) while (...) { ... } 

etc ... @autoreleasepool blocks are no different.

+1
source

Source: https://habr.com/ru/post/1498956/


All Articles