tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Nested functions [was Re: valgrind]



On Mar 24, 2022, at 8:16 PM, Mouse <mouse%Rodents-Montreal.ORG@localhost> wrote:

Nested functions are not closures, or at least not what I know as
closures.  A nested function pointer (conceptually) goes invalid as
soon as anything it refers to goes out of scope, or at the latest as
soon as its smallest enclosing block exits (or possibly when its
smallest enclosing function returns).  The thing I know as a closure
would preserve the referred-to objects as long as the closure is
potentially callable.  This requires more reference tracking than C
typically makes possible.

Closures can easily be used as nested functions, and the blocks feature that was created by Apple explicitly addresses this by including runtime functions.

1. You can just declare and use a block if it's not going to go out of scope, as if it were a nested function, with just slightly different syntax than nested functions. (You do this by declaring a block-typed variable and immediately assigning the block to it, then calling through the variable. It behaves like a function pointer.)

2. If you have a variable in the outer scope that you want to modify in the block, you have to annotate the variable with __block, so the block context (activation record) created for the bock can find it. Otherwise everything in the enclosing scope is effectively immutable (though one must of course be aware that an immutable pointer is not the same as a pointer to immutable data).

3. If you're passing the block to another function or block, whatever you pass it to should *either* annotate its block argument as non-escaping via the right __attribute__(()) to indicate it doesn't need any memory management, or it should Block_copy() the block it's handed and work only with the copy. That ensures the block context is hoisted to the heap. Following Apple's general patterns, a Block_copy() of a heap block is identical to a BlocK_retain() so the latter should really never be called.

4. If something calls Block_copy() because it wants to hold onto a block, it needs to call Block_release() to eventually dispose of the block.

Here are the language and runtime specs. They're a great language addition and used pervasively on Apple platforms as a result.

Language: https://clang.llvm.org/docs/BlockLanguageSpec.html
Runtime/ABI: https://clang.llvm.org/docs/Block-ABI-Apple.html

  -- Chris



Home | Main Index | Thread Index | Old Index