560 karma · joined March 29, 2020
However, this is not without precedence in C. For example, just look at the for loop:
for (clause1; expression2; expression3) statement
expression3 is executed after statement.
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[1] Watcom C Library Reference Version 1.8. Open Watcom. 2008. ftp://ftp.openwatcom.org/manuals/current/clib.pdf
[2] Safe C Library — A full implementation of Annex K https://github.com/rurban/safeclib/
[3] slibc https://code.google.com/archive/p/slibc/
By the time the ISO/IEC TR 24731-1:2007 was released, and then later Annex K added to the C Standard, Microsoft had to decide if they wanted to change the interfaces to conform to the changed standard and re-implement their code bases. They presumably decided that they did not, which I think is a defensible decision.
As to unergonomic, examples please?
- signed integer overflow or division by zero occurs, a division instruction traps on x86, while it silently produces an undefined result on PowerPC - left-shifting a 32-bit one by 32 bits yields 0 on ARM and PowerPC, but 1 on x86; - left-shifting a 32-bit one by 64 bits yields 0 on ARM, but 1 on x86 and PowerPC
#define DEFER(a, b, c) \
for (bool _flag = true; _flag; _flag = false) \
for (a; _flag && (b); c, _flag = false)
int fun() {
DEFER(FILE *f1 = fopen(...), (NULL != f1), mfclose(f1)) {
DEFER(FILE *f2 = fopen(...), (NULL != f2), mfclose(f2)) {
DEFER(FILE *f3 = fopen(...), (NULL != f3), mfclose(f3)) {
... do something ...
}
}
}
}
We are also looking at the attribute cleanup. Sounds like you should be involved in developing this proposal?We have dropped support for sign and magnitude and one's complement architectures from C2x (a decision Doug Gwyn does not agree with). There was some concern that Unisys may still use a one's complement architecture, but that this may only be in emulation nowadays.
N2198 2018/01/02 Ballman, Adding the u8 character prefix
Sounds like you don't care for Annex K. What don't you like about it?
Making C friendlier is always a good idea, and I think the committee is (slowly) working towards this goal. I would have to examine these papers by John Regehr in more detail. Looking quickly at his proposals I can see why there he couldn't find consensus for these ideas as some of them do appear controversial.
An example of a friendly dialect of C is always is C0 (C-naught) from CMU. I don't think I'm exaggerating when I say that this language has not "caught on".
My job at NCC Group involves a lot of code reviews, so frequently the files that are of interest to me are the ones that contain the most defects. I typically identify these by compiling with compiler warnings turned up and warning suppression turned down. I'll frequently also make use of static and dynamic analysis, including the GCC and Clang sanitizers.