|
|
|
|
|
by Asooka
2017 days ago
|
|
I suspect it will come with some really big caveats. For instance what you wrote shouldn't compile, because i's storage duration doesn't extend to the end of the guard block. If you write guard {
int i;
for (i=0; i<n; i++) defer foo(i);
}
I would expect foo(n) to be called n times. That is, variables won't be captured, it would work literally as if you wrote "foo(i)" n times at the end of the guard block. It's a footgun, but everything in C is a footgun and this behaviour is not surprising to me as a C developer.So I expect the implementation would be 1. If a defer block references variables which do not live to the end of the guard block, the program is malformed (compiler error). 2. Compile each defer block as if it was written at the end of the guard block. What order the defer blocks are stored in is implementation-defined 3. Put a pointer on the stack each time a defer statement executes pointing to the compiled defer statement. With this each defer statement is just a few bytes of overhead added to the stack and you can do it in a loop, though it may not do what you expect if you come from Go. For the example I expect the compiler to emit code similar to: struct defer_node {
void **label;
struct defer_node *next;
};
struct defer_node *defer_start=0;
int i;
for (i = 0; i < n; i++) {
struct defer_start *defer_new = alloca(sizeof(struct defer_node));
defer_new->label = &defer_stmt0;
defer_new->next = defer_start;
defer_start = defer_new;
}
while (defer_start) {
goto *defer_start->label;
defer_stmt_exit:
defer_start = defer_start->next;
}
return;
/* or break; or continue; whatever is appropriate for the enclosing block */
defer_stmt0:
foo(i);
goto defer_stmt_exit;
This makes defer more or less just a mechanical transformation of code that can be expressed with existing C primitives and without requiring dynamic memory. I think it would be a good addition to C's structured programming elements. |
|
This still makes it really easy to overflow your stack, especially if for example your loop count above can come from user input. This is dangerous for all the same reasons that variable-length arrays are dangerous.