-
Notifications
You must be signed in to change notification settings - Fork 6
Deep C notes
Notes from Deep-C
off_t end = pos + PREFIXLEN(buf);
where PREFIXLEN(buf)
does (buf[pos++] | (buf[pos++] << 8))
and the scenario for VINTPREFIX(buf) is worse since it introduces control points (i.e the value has more bytes if MSB is 1) within the section.
This bit us badly when we switched compilers and tests started to fail. We had to crawl through gcc -E to find it.
The other bit of unspecified behaviour kicked in when we had -O3 enabled and strict-aliasing, basically with allocations and I/O sections mixed with macros which cast it into structs. Something like
#define WRITE_MESSAGE(buf, pos, tag, value) do {
Msg* msg = (Msg*)(buf[pos]);
msg->tag = tag;
msg->value = value;
pos += size(msg);
} while(0)
int8_t *buf = malloc(...);
buf[0] = 0; // always zero out buf[0]
pos = 0;
if(...) {
WRITE_MESSAGE(buf, pos, 0, 42);
}
// now any check on buf[0] results in invalid assembly due to aliasing
This didn't warn with -Wall and we hit a problem with -O3.
Btw as an example of bad-code ideas inherited by Ruby programmers, here's my favourite fake-closure sample
typedef int (*intfun)(int i);
intfun make_adder(int i)
{
int add(int k)
{
return (i+k);
}
return add;
}
int main()
{
intfun foo;
foo = make_adder(2);
printf("%d\n", foo(3));
return 0;
}
This is what you have to do to make real closures in C - x86-native-closures
And as for the variable shadowing problem, I dug up my old GCC bug-report (on the lack of warnings) - gcc-bug #19099