(no title)
rseacord | 5 years ago
This case of the defer in the loop is frequently cited, probably because it is a problematic case. However, I looked at a lot of real code and the only case I found of resources being allocated in a loop they were allocated at the beginning of the loop and deallocated at the end. Another option we are considering is to use the scope for the guarded block. In this case, deferred statements would be executed at the end of each iteration of the for loop which would be ideal for this sort of code. For example, you could rewrite this function using defer:
https://github.com/openssl/openssl/blob/a829b735b645516041b5...
like this:
for (;;) {
raw = 0;
ptype = 0;
i = PEM_read_bio(bp, &name, &header, &data, &len);
defer {
OPENSSL_free(name);
name = NULL;
OPENSSL_free(header);
header = NULL;
OPENSSL_free(data);
data = NULL;
}
...
} else {
/* unknown */
}
} // end for loop, run deferred statements
mskslal|5 years ago
eqvinox|5 years ago
I would strongly agree that the dedicated guard{} block is a bad idea and this should just tie into the innermost scope. I see what this is trying to do ("if (...) { foo.x = malloc(); defer free(foo.x); }") but you don't solve a UI problem (as in, user interface for the programmer to their code) by adding more weird UI.
("Worst" example for shooting yourself in the foot: defer inside macros. Programmer then forgets that the macro contains a defer, and the defer defaults to the function-implicit outer guard block. But it's really in a nested loop. That's gonna be a fun week of debugging... much less of a risk when you have the guarantee in terms of innermost scope.)
gpderetta|5 years ago
dooglius|5 years ago
gustedt|5 years ago