A note for C programmers

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

User avatar
lucasart
Posts: 3232
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: A note for C programmers

Post by lucasart »

mar wrote:
Sven Schüle wrote:See my comments above.
They never read, they never listen, they're always right, they're never wrong. Guess who? :wink:
Indeed. Impossible to have a discussion without these arrogant lecturers jumping in the middle of it, trying to patronize you about trivial stuff that has nothing to do with the subject...
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.
User avatar
lucasart
Posts: 3232
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: A note for C programmers

Post by lucasart »

syzygy wrote:
lucasart wrote:Some of the other mistakes are quite obvious. For example: who would, deference a pointer, and check for nullity of the pointer after doing it? Idem for division by zero.
I wouldn't call that obvious at all.

Code: Select all

  if (arg2 == 0)
    ereport(ERROR, (errcode(ERRCODE_DIVISION_BY_ZERO),
                     errmsg("division by zero")));
  /* No overflow is possible */
  PG_RETURN_INT32((int32) arg1 / arg2);
It is clear that ereport() is intended to exit the program with a sensible error message. Depending on the kind of program it might not make sense to do anything else. The code looks quite natural and my first thought on reading it is certainly not that the check might get optimised away.

One way of fixing this is to mark the function ereport() with the attribute "noreturn". I suppose clang (which apparently does optimise the above check away) supports this attribute. But it is obviously not part of the C standard.

I guess the "standard C" way of doing this is to insert an "else".
Good point. The examples I had in mind were the stupid ones where the guy deferences a pointer before checking its nulity, and same for divide by zero. Clearly the programmer was at fault in these cases.

The exampole you show is -- I believe -- an abusive optimiation by the compiler (IOW a true GCC bug). AFAIK there is nothing in the standard that allows the compiler to perform that optimization. The "as if" of the standard does not apply here, unless the compiler can prove that the ereport() function cannot change the control flow. Obviously, if there is an exit() statement somewhere in the *possible* call tree of ereport(), as well as a longjmp() or a throw in C++ for example, the compiler cannot make such an assumption.

Perhaps using flto fixes the problem, as the code is generated at link time from the bytecode produced at compile time (so the code of ereport() is visible, rather than just an extern declaration). I think this one is a true GCC bug.
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: A note for C programmers

Post by bob »

lucasart wrote:
bob wrote:
Sven Schüle wrote:
lucasart wrote:According to the first paper, the C standard permits even crazier optimizations. Apparently (I was not aware of it and still cannot believe it myself), these two expressions are not equivalent:

Code: Select all

a[x ? 1 : 0]
a[x != 0]
The second one is fine, and no standard compliant compiler will break this code. But the first one is dangerous. The compiler is allowed to assume that x can only be 1 or 0, hence replace it by a[x]. This is a "nice" optimization because it produces branch-less code. The problem is that when x is not 0 or 1, all hell breaks loose. The program could cause segfault (if you're lucky!) or break silently...
Where do you get this from? In a boolean context "x" means "x != 0". I don't think that the standard allows to replace a[x ? 1 : 0] by a[x] since in the "?" expression "x" is in boolean context but in a[x] it is integer. This would break semantics, and also there is nothing about "undefined behaviour" here, it is simply "boolean vs. integer context". The first paper is also not the C standard, and in my view it contains several unproven statements. Many of them may be true, and I do not say that this paper is bad in general (there is even a lot of interesting stuff in it), but this "a[x]" point seems a bit far-fetched to me.

Note also that the original quote from the first paper is slightly different, it says:

Code: Select all

if (cond) {
    A[1] = X;
} else {
    A[0] = X;
}
where "cond" is definitely meant as a boolean expression which always evaluates to 0 or 1.

Sven
He should compile this and look at the asm:

x = !x;

It has a conditional test. :)

where the simpler

x ^= 1;

just flips a 0 to a 1 or vice-versa

Here's gcc 4.7.3's take on x = !x

testl %eax, %eax
sete %al
movzbl %al, %esi

as opposed to a single xor instruction.
Your x = !x is completely unrelated to our discussion. Besides, I never claimed that x != 0 or (x ? 1 : 0) were branch-less (if that's the part of my post you misread that lead you to x = !x). I said that a[x] was branch-less.

The problem is that the author of the paper on dangerous optimizations made a mistake in his claim that a compiler is allowed to replace

Code: Select all

if (x)
  a[1] = 0;
else
  a[0] = 0;
by

Code: Select all

a[x] = 0
This was never MY CLAIM. I just said that's what the paper said, and I did not believe it, although I had not read the standard to check. Martin has checked the standard, and that claim is wrong. That's all.
You can not replace the !x with an array reference. Because the C semantics clearly state "with the expression !x, if x == 0, then !x =1, if x == anything other than zero, !x = 0. That was what the original poster reacted to and I simply gave a programming example which shows that the array approach is completely nonfictional.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: A note for C programmers

Post by bob »

lucasart wrote:
mar wrote:
Sven Schüle wrote:See my comments above.
They never read, they never listen, they're always right, they're never wrong. Guess who? :wink:
Indeed. Impossible to have a discussion without these arrogant lecturers jumping in the middle of it, trying to patronize you about trivial stuff that has nothing to do with the subject...
Arrogant indeed. Look at the topic of the thread "C programmers". We don't have any "bool" data type. We have ints and floats. Helps if you read along the thread before popping off with something that is irrelevant...

This was ALWAYS about C.
stevenaaus
Posts: 608
Joined: Wed Oct 13, 2010 9:44 am
Location: Australia

Re: A note for C programmers

Post by stevenaaus »

bob wrote:
mvk wrote:
bob wrote:On Apple Mavericks, all you see is "Abort". No hint about what the problem was, no nothing. Running under the debugger shows absolutely nothing either. Nice software design.
There is a message logged to the system log, as was mentioned before. Just open de Console application and read "crafty: detected source and destination buffer overlap". And then a nice readable crash report is saved in ~/Library/Logs/DiagnosticsReports/, containing, amongst others, a stack trace.
Fine. I am SURE every C programmer on the planet is aware of such. Makes a lot more sense than displaying an error message right out of the library like "Abort(source and destination strings overlap)". Let's put it in a non-obvious place and see if the programmer can find it.
OS X is a funny thing. Mavericks seems to have broken lots of stuff.
Do they really alias gcc to clang ? That's bizarre.

Generally i agree with Linus. Here is a thread where he has his say
http://sourceware.org/bugzilla/show_bug.cgi?id=12518
User avatar
michiguel
Posts: 6401
Joined: Thu Mar 09, 2006 8:30 pm
Location: Chicago, Illinois, USA

Re: A note for C programmers

Post by michiguel »

mar wrote:
Sven Schüle wrote:See my comments above.
They never read, they never listen, they're always right, they're never wrong. Guess who? :wink:
Me? Why?

Miguel
Daniel Shawul
Posts: 4185
Joined: Tue Mar 14, 2006 11:34 am
Location: Ethiopia

Re: A note for C programmers

Post by Daniel Shawul »

michiguel wrote:
mar wrote:
Sven Schüle wrote:See my comments above.
They never read, they never listen, they're always right, they're never wrong. Guess who? :wink:
Me? Why?

Miguel
Not directed at you, but I wonder what the point of this discussion is anyway?
Afterall this forum is for computer chess programming not for computer programing. There are tons of computer programing forums out there for those who want to flex their programing muscles. If I want to discuss my programing issues, I would go there! Only in our chess programing forums are tangential discussions that are irrelevant, like this one, are allowed.
Computer Go, Computer checkers and other game programing forums I know of doe not allows nonsense like these.
IMHO-YMMV
syzygy
Posts: 5557
Joined: Tue Feb 28, 2012 11:56 pm

Re: A note for C programmers

Post by syzygy »

lucasart wrote:The exampole you show is -- I believe -- an abusive optimiation by the compiler (IOW a true GCC bug). AFAIK there is nothing in the standard that allows the compiler to perform that optimization. The "as if" of the standard does not apply here, unless the compiler can prove that the ereport() function cannot change the control flow. Obviously, if there is an exit() statement somewhere in the *possible* call tree of ereport(), as well as a longjmp() or a throw in C++ for example, the compiler cannot make such an assumption.
I agree, even if a function is not guaranteed to not return, in a specific case it might not return and the undefined behavior would/should never be triggered.

More generally, I don't think "provably" undefined behavior later in the program should allow a compiler to optimise the whole program away. The computer should do exactly what the programmer told it to do (in particular cause all the externally visible side effects), up to the point that it actually runs into the undefined behavior. In other words, undefined behavior may cause demons to fly out of your nose, but it may not result in time travel.
Perhaps using flto fixes the problem, as the code is generated at link time from the bytecode produced at compile time (so the code of ereport() is visible, rather than just an extern declaration). I think this one is a true GCC bug.
You probably mean clang bug, if clang in fact does what the author suggests it does.

But maybe I should read the paper again to be sure that I understand the author's point and that I am not reading too much into it.

edit: oops, this was indeed about gcc. More reason to study the paper a bit better.
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: A note for C programmers

Post by Sven »

lucasart wrote:
mar wrote:
Sven Schüle wrote:See my comments above.
They never read, they never listen, they're always right, they're never wrong. Guess who? :wink:
Indeed. Impossible to have a discussion without these arrogant lecturers jumping in the middle of it, trying to patronize you about trivial stuff that has nothing to do with the subject...
I see absolutely no need to use the word "arrogant" in the context of a technical discussion.
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: A note for C programmers

Post by Sven »

bob wrote:
lucasart wrote:
mar wrote:
Sven Schüle wrote:See my comments above.
They never read, they never listen, they're always right, they're never wrong. Guess who? :wink:
Indeed. Impossible to have a discussion without these arrogant lecturers jumping in the middle of it, trying to patronize you about trivial stuff that has nothing to do with the subject...
Arrogant indeed. Look at the topic of the thread "C programmers". We don't have any "bool" data type. We have ints and floats. Helps if you read along the thread before popping off with something that is irrelevant...

This was ALWAYS about C.
The point was never about "bool" data type but about a conditional expression which is also called a "boolean" expression. That certainly exists in C.