Live data from Hacker News

I Do Not Know C: Short quiz on undefined behavior (2015)

kukuruku.co

181–189 of 189 posts

Re: I Do Not Know C: Short quiz on undefined behavior (2015)

#181
post #78

Earlier quoted context omitted.

In the large, no, they don't care about the 90-95% of the code base that's not performance critical. And these days, the stuff that is critical will be #ifdef and asm(...) stew. I can't tell you how many projects I have been on where disabling optimization made no measurable difference in performance. This being said, I cannot speak for game devs nor video device driver developers.

I have to say, I have never encountered a program where compiling without optimizations made no difference. If you have seen that, then I would agree that C was a very, very poor choice for that particular domain.

It made no measurable difference. The acceptance criteria for the system were not materially affected. Since the optimization did not improve the performance by that, it was generally set one way ( mostly off ) and let that way.

Teams I'm on have written some tight - but readable -code, too. Well-architected, low-latency, low-jitter.

Re: I Do Not Know C: Short quiz on undefined behavior (2015)

#182
post #108
post #78

Earlier quoted context omitted.

I have to say, I have never encountered a program where compiling without optimizations made no difference. If you have seen that, then I would agree that C was a very, very poor choice for that particular domain.

Business applications, as it was common in the 90's. Witting them in C or VB made no difference for the guys sitting at the desk.

This ranged from networking equipment to phone switches to equipment control. Most of it was bare metal.

I've never written a business application in my life.

Re: I Do Not Know C: Short quiz on undefined behavior (2015)

#183

Earlier quoted context omitted.

In the large, no, they don't care about the 90-95% of the code base that's not performance critical. And these days, the stuff that is critical will be #ifdef and asm(...) stew. I can't tell you how many projects I have been on where disabling optimization made no measurable difference in performance. This being said, I cannot speak for game devs nor video device driver developers.

You can try an experiment and build an application like Firefox from source with disabled optimizations. I bet you'll notice a massive difference. Even more important are things that run in datacenters on thousands and thousands of machines. Even if you suppose that optimizations make only a minuscule difference on the scale of today's infrastructure 5% fewer machines can save huge amounts of electricity.

Why would I want to build Firefox from source? I don't build things that run on thousands of machines. Last thing I ran any code on had a 2500 HP diesel; the electronics were in the noise.

Re: I Do Not Know C: Short quiz on undefined behavior (2015)

#184
post #81

Earlier quoted context omitted.

I read this as, will confuse the snot out of hapless newbie programmers trying to learn C via stepping though their code in an IDE. While providing no practical benefit to programmers writing production code.

It is necessary in order for the compiler to do transformation optimizations which do impact production code. Newbies shouldn't be writing production code without guidance anyways IMO.

Newbies should probably turn off optimization entirely.

Re: I Do Not Know C: Short quiz on undefined behavior (2015)

#185

Earlier quoted context omitted.

C programmers expect dead code removal. Especially when the compiler also inlines functions (and, of course, inlining makes the biggest impact on short functions; and one way to get short functions is to have aggressive dead code removal). And macros can expand into very weird, but valid, code; so the statement that "nobody would ever write code like that" isn't relevant. The compiler may well have to handle unnatura…

OK, I think I see what SHOULD happen here. It's been forever since I've actually compiled a C program not part of some package I was installing, BUT. * There should be a warning flag, and it should be ON BY DEFAULT, that //all// code removal is stated, and the logic behind it given. * It should be possible to elevate that condition to an error (and that too might even be the default).

I have no idea if it's true, but compiler implementers swear that their compilers perform so many optimizations, and that those optimizations allow additional optimizations, that this kind of approach would bury you in messages.

Re: I Do Not Know C: Short quiz on undefined behavior (2015)

#186

Earlier quoted context omitted.

It means that empty loops (loops with empty bodies) can be completely removed if the controlling expression has no side effects. > This is intended to allow compiler transformations such as removal of empty loops even when termination cannot be proven. It means while(i) {} can be eliminated as if i were 0, because there are no side effects in the loop expression or the loop body, and what would be the point of the lo…

It's quite common in embedded systems to have the fault handler end with an infinite loop, to give the programmer a chance to attach a debugger an inspect the call stack. Sometimes this behavior is turned on or off with a debug flag, which can trigger this unexpected optimization if the flag is not a compile time constant.

A halt instruction (HLT on x86) might also work.

Re: I Do Not Know C: Short quiz on undefined behavior (2015)

#187
post #178

Earlier quoted context omitted.

> Well, firstly it's pretty unsatisfying to hear that yes, this API contravenes strict aliasing restrictions, but only on the library side! - essentially that it is impossible to implement the sockets C API in C. Then it'd also be pretty unsatisfying to hear that it's impossible to write an OS kernel in standard C too - it requires compiler extensions for lots of various details. It's impossible to write a standard C…

Strictly speaking, that's not true. You can examine it directly, but it requires casting the `struct sockaddr * ` to a `sa_family_t * ` instead. This is valid because regardless of what type of object it really is, it must start with a `sa_family_t` entry,... No, that isn't guaranteed by POSIX - it has to have an sa_family_t member, but it doesn't have to be the first one. I also think it's problematic that the use e…

I'm gonna try to address everything I can in this reply. Sorry it has taken so long.

> C compilers existed in 1989 that would assume different structure types with common initial sequences couldn't alias? With the "common initial sequence" carve-out in §3.3.2.3? I am sceptical...

That's not quite what I was talking about. What some compilers would do is not generate extra reads when you had a `long * ` and a `int * ` in the same scope - with the idea being that those two cannot point to the same data, and thus it is not necessary to reread the data from the `int * ` when you write to the `long * `. Compilers have now taken it a slight step further - an `int` that belongs to a `struct a` and an `int` that belongs to a `struct b` can't alias - but it is really not much different from the original idea (And hence why it is legal). What the standard really describes is that objects have a single defined type and that accessing objects though a type other then their original type is invalid, which fits with what compiler writers have taken to doing. That said, I would not be opposed to the standard simply making that legal. While avoidable in most cases, it does cause problems in some instances (BSD sockets being a very notable example), and I'd wager it only brings marginal optimizations (for which `restrict` already provides a solution).

> I do not think this is that easy when you include sockaddr_un into the mix, because of the way that sockaddr doesn't include the full size of its path member. This is, in fact, the point that I throw up my hands and use -fno-strict-aliasing because the fact that pointer provenance, rather than just value and type, is important together with the fact that it's not actually clear whether you've correctly laundered the pointer through a union or not, makes it all too... grey.

Technically, you could use a `char` array for the `sockaddr_un`, and then just cast it to the right type. That's legal because `char` can alias. That said I'm fairly sure that `sockaddr_un` has a defined size - it doesn't use a FAM in implementation, it's just that the length of it's path member can vary. The POSIX standard isn't as clear as can be, but notes that it is left undefined only for the reason that different Unix's use different max lengths, and it says that it's typically somewhere in the range of 92 to 108. That along with the typical usage of `sockaddr_un` implies to me that it is perfectly fine to declare one, it just doesn't have a guaranteed length. Used in a `union` it should be fine. (All that said, I think what you've said also shows another current issue with C - there should be a way to statically declare a `struct` that has a FAM at the end by providing the length for the FAM. There's no way to do this currently except using a `char` array and casting, which is not an acceptable solution IMO).

On that note though, the entire issue here could actually be largely resolved by simply adding the `may_alias` gcc attribute to the definition of `struct sockaddr` (And `struct sockaddr_storage`). It would declare that a `sockaddr` can alias any other type you want, and thus would make it legal to read from a `sockaddr` and then cast it to another type for use - removing the need for the `union` BS and all the other various hacks to get around this issue. Obviously that's not standard C, but I think it makes a pretty good argument that adding something like `may_alias` to the standard would be a very good addition.

And that touches only the larger problem with strict-aliasing that I see - there's no way to avoid it. We have `restrict` which ironically allows us to avoid the aliasing problem for pointers which strict-aliasing doesn't apply, but we have no way to tell the compiler two pointers (or types) can alias when it thinks they can't. `may_alias` is one solution, but really any solution that fixes would problem would be extremely welcome in my book. I think the standards writers currently consider `union` to be the solution, but IMO that's simply not sufficient.

> No, that isn't guaranteed by POSIX - it has to have an sa_family_t member, but it doesn't have to be the first one. > > I also think it's problematic that the use explicitly contemplated by POSIX is considered ill-formed C.

As long as all the sa_family_t members in all of the various `sockaddr` types overlap then you could make it work (If they don't overlap I fell like that would create lots of other issues). Obviously though this is a pretty clumsy solution.

And I would agree - I wouldn't say it's anybodies particular fault that we've hit this particular point (Though you could argue that compiler writers jumped the gun on this one), but it is an issue worth addressing. I do think it's possible to use it correctly through the usage of a few different techniques, but 1. most programs already written don't do that, and 2. like I said before, you shouldn't have to go through a million hoops (that aren't even mentioned) to use the interface correctly.

Re: I Do Not Know C: Short quiz on undefined behavior (2015)

#188

Earlier quoted context omitted.

Maybe we mean different things by the word "simple". What language do you think is simpler than C?

Scheme, ML, Java, Lua...

Yeah, we must have different definitions of simplicity, as I expected.

Just off the top of my head, Java has the following complexities that C lacks: exceptions, garbage collection, class inheritance, generics, and a very large standard library.

What definition of simplicity are you using when you say Java is simpler than C?

Re: I Do Not Know C: Short quiz on undefined behavior (2015)

#189

Earlier quoted context omitted.

It is necessary in order for the compiler to do transformation optimizations which do impact production code. Newbies shouldn't be writing production code without guidance anyways IMO.

Newbies should probably turn off optimization entirely.

No argument there, or at the very least whole program optimizations
Post reply on HN