Author Topic: An 'interesting' thing you can do in C++  (Read 18465 times)

0 Members and 1 Guest are viewing this topic.

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3137
  • Country: ca
Re: An 'interesting' thing you can do in C++
« Reply #100 on: September 12, 2018, 11:14:33 pm »
In my view C is like a small sports car with manual gearbox, no ABS, no airbags, no traction control etc. If you can handle the challenge you will drive very fast on the twisty roads, but it will not be a SUV with all the latest driver aids.

No, that's assembler :)
 
The following users thanked this post: hans

Online brucehoult

  • Super Contributor
  • ***
  • Posts: 3998
  • Country: nz
Re: An 'interesting' thing you can do in C++
« Reply #101 on: September 12, 2018, 11:23:39 pm »
No undefined situation. What am I missing?
Isn't the right side of an assignment always evaluated first?
You are missing what is written in the C standard. Left vs. Right does not matter. The simple rule is that you may not modify  s variable more than once between sequence points. The assignment is not a sequence point; the next one is at the semicolon.

For a=a++; the compiler is allowed to Instruct the processor to execute a=a and a++ at the same time for efficiency. In this case this creates a race condition or nasal daemons.

No, that's not nasal demons. After "a=a++;", a will either have the same value as before, or will be incremented by 1. There are no other options. The program will not crash. Your computer will not catch on fire. Demons will not fly out of your nose (or your arse). The result is boundedly undefined.
 
The following users thanked this post: hans

Offline MK14

  • Super Contributor
  • ***
  • Posts: 4527
  • Country: gb
Re: An 'interesting' thing you can do in C++
« Reply #102 on: September 12, 2018, 11:41:55 pm »
In my view C is like a small sports car with manual gearbox, no ABS, no airbags, no traction control etc. If you can handle the challenge you will drive very fast on the twisty roads, but it will not be a SUV with all the latest driver aids.

No, that's assembler :)

Assembler = Motorbike.
That is why windows can't be written in assembler. Because motorbikes never (usually) have doors, so there is no room for any windows.
 
The following users thanked this post: Siwastaja

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3137
  • Country: ca
Re: An 'interesting' thing you can do in C++
« Reply #103 on: September 12, 2018, 11:50:47 pm »
After "a=a++;", a will either have the same value as before, or will be incremented by 1. There are no other options. The program will not crash. Your computer will not catch on fire. Demons will not fly out of your nose (or your arse). The result is boundedly undefined.

Not sure about C++, but the plain C allows the compiler to do practically anything:

"Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or
execution (with the issuance of a diagnostic message)."

Of course, the real compiler will perform the operations one way or another, but it doesn't have to.
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4196
  • Country: us
Re: An 'interesting' thing you can do in C++
« Reply #104 on: September 13, 2018, 12:16:56 am »
Quote
Code: [Select]
(argc == 2 ? a : b) += 5;

Quote
For what it's worth, I'm a long-time C programmer and had no trouble at all understanding what the code in OP did.

A agree that this particular example is pretty easy to understand, and indeed my first reaction was more along the lines of "oh?  Didn't that work before?  Oh, right...")
But I don't really see any reason to specifically ADD the ability to do this to the language specification, either.
Haven't we outgrown the whole "COBOL is much too verbose; we're going to write APL/Forth/C so that you'll have to type a lot less!" thing?
 

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 8110
  • Country: fi
Re: An 'interesting' thing you can do in C++
« Reply #105 on: September 13, 2018, 06:25:03 am »
In my view C is like a small sports car with manual gearbox, no ABS, no airbags, no traction control etc. If you can handle the challenge you will drive very fast on the twisty roads, but it will not be a SUV with all the latest driver aids.

Not bad!

I'd add that maybe C is like a 70's to 80's Toyota Corolla. Widely used in its simplest form, most people aren't super excited about it, but it does the job fine and economically time after time. At the same time, others have found out you can tune the shit out of it to extract performance and do "tricks" that weren't in the original "marketing" - and doing this is relatively simple. While it doesn't have airbags, it's not the most inherently unsafe thing ever, either.

And, while expensive and fast "sports cars" do exist,  they are heavy, clumsy to also perform everyday tasks with, are black boxes of complexity, and tend to suddenly catch fire while sitting in traffic lights, or just offer so much power in one place that their young, inexperienced owners tend to epidemically crash them (to make headline videos on internet video news sites designed for envious, poor people to laugh at). I don't know which programming language these cars would represent, but IMHO, at least not C. Maybe C++?

Me? I drive a 1988 Toyota Carina II, rusty as hell but does the job, and write in C, rusty as hell but does the job.
« Last Edit: September 13, 2018, 06:40:40 am by Siwastaja »
 
The following users thanked this post: MK14

Offline MK14

  • Super Contributor
  • ***
  • Posts: 4527
  • Country: gb
Re: An 'interesting' thing you can do in C++
« Reply #106 on: September 13, 2018, 06:36:37 am »
I'd add that maybe C is like a 70's to 80's Toyota Corolla.

That's good.

So an interpreted/scripted language = Horse and Cart.
Because a Horse and Cart is very simple and somewhat quick to assemble/make. Not fast, by any stretch of the imagination.

VHDL/Verilog
FPGA = Jet Aircraft
ASIC or full custom IC = Space Rocket
 

Offline MK14

  • Super Contributor
  • ***
  • Posts: 4527
  • Country: gb
Re: An 'interesting' thing you can do in C++
« Reply #107 on: September 13, 2018, 07:13:39 am »
No, that's not nasal demons. After "a=a++;", a will either have the same value as before, or will be incremented by 1. There are no other options. The program will not crash. Your computer will not catch on fire. Demons will not fly out of your nose (or your arse). The result is boundedly undefined.

The thing is that the compiler, has been designed to a certain defined specification (The C or applicable, standard). So, since the operation is UNDEFINED, the compiler has NOT (necessarily) been designed to include the capabilities to correctly compile such code.

So you can't (with 100% reliability), say "it will always be the same or same plus 1 value, never anything else".
Since you have gone outside of the allowable limits of the compiler (exceeded Absolute Maximum values, if you want a datasheet analogy).
Therefore, absolutely anything can happen.

Just like exceeding the maximum capabilities of a transistor.
The overloaded transistor, may carry on working, it may let out the magic smoke, it may catch on fire and explode.
It may eject a high copper content vapour, which when your mother breathes it in, changes her colour to GREEN, and when you breath in the magic smoke you may cough out terrible demons.
« Last Edit: September 13, 2018, 07:18:04 am by MK14 »
 

Offline GeorgeOfTheJungle

  • Super Contributor
  • ***
  • !
  • Posts: 2699
  • Country: tr
Re: An 'interesting' thing you can do in C++
« Reply #108 on: September 13, 2018, 07:47:58 am »
Nope, I'm with brucehoult on this one, our mothers are safe.
The further a society drifts from truth, the more it will hate those who speak it.
 

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1714
  • Country: se
Re: An 'interesting' thing you can do in C++
« Reply #109 on: September 13, 2018, 08:07:19 am »
Nope, I'm with brucehoult on this one, our mothers are safe.
I'm partially in total disagreement.
Our mothers might be safe, but hyperbole is a man's best friend.

Unfortunately I have lost the example (code, specific version of gcc and flags used) where a similar line was completely ignored by the compiler.
Skipped, no code emitted, no warning.
The result was that a block local variable would keep its random uninitialized value.

Nandemo wa shiranai wa yo, shitteru koto dake.
 
The following users thanked this post: MK14

Offline glarsson

  • Frequent Contributor
  • **
  • Posts: 814
  • Country: se
Re: An 'interesting' thing you can do in C++
« Reply #110 on: September 13, 2018, 08:12:16 am »
No, that's not nasal demons. After "a=a++;", a will either have the same value as before, or will be incremented by 1. There are no other options. The program will not crash. Your computer will not catch on fire. Demons will not fly out of your nose (or your arse).
Anything can happen.
Only fools think that a=a++; is a reasonable thing to write. I don't know what they thing it will accomplish. A more reasonable, but also sinister, situation is when a and a has different names and are pointers pointing at the same variable. On a supetscalar processor the instructions might then be
  move @a,@b
  add @a,@b,1
with both instructions executing at the same time. When both instructions retire and both attempt to update what a points to (@a) at the same time, the processor will detect this and raise some low level exception. If this happens in your nose transplant then nasal daemons is a reasonable result.
 
The following users thanked this post: newbrain, MK14

Offline GeorgeOfTheJungle

  • Super Contributor
  • ***
  • !
  • Posts: 2699
  • Country: tr
Re: An 'interesting' thing you can do in C++
« Reply #111 on: September 13, 2018, 08:32:50 am »
Only fools think that a=a++; is a reasonable thing to write.

That much is clear! (I hope)

I'm partially in total disagreement.

LOL

Quote
The result was that a block local variable would keep its random uninitialized value.

If a was uninitialized before that line, it would have to remain so after it, so that's ok, isn't it?
The further a society drifts from truth, the more it will hate those who speak it.
 

Offline hamster_nzTopic starter

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: An 'interesting' thing you can do in C++
« Reply #112 on: September 13, 2018, 08:44:48 am »
No, that's not nasal demons. After "a=a++;", a will either have the same value as before, or will be incremented by 1. There are no other options. The program will not crash. Your computer will not catch on fire. Demons will not fly out of your nose (or your arse).
Anything can happen.
Only fools think that a=a++; is a reasonable thing to write. I don't know what they thing it will accomplish. A more reasonable, but also sinister, situation is when a and a has different names and are pointers pointing at the same variable. On a supetscalar processor the instructions might then be
  move @a,@b
  add @a,@b,1
with both instructions executing at the same time. When both instructions retire and both attempt to update what a points to (@a) at the same time, the processor will detect this and raise some low level exception. If this happens in your nose transplant then nasal daemons is a reasonable result.

I too am with Bruce Holt. "a = a++;" is perfectly valid C code. It might be stupid code, but I expect that no C compiler will kill my dog because I run this code.

The only think in dispute is what it's outcome will be, as there is no implicit sequence to the "load", "store" and "increment" operations. The issue is that the compiler and CPU is free to schedule store and increment order it likes, and can change that order depending on a whim.

Likewise there is nothing wrong with this code:

Code: [Select]
   *p1 = (*p2)++;

but if p1 == p2, then the value pointed to be p1 then the program's memory may not change as I expect. My dog will still be safe.

All languages have undefined corners and rough edges, they are fun to peak into when bored, but I am sure we all agree  in general you stay away from them so your code works reliably, predictably and can be maintained.

Integer addition can lead to undefined behavior, as can subtraction, and multiplication, and division... you really don't have much left that is always guaranteed to never shoot yourself in the foot, regardless of language - you just have to know when you are in the "safe operating area" of the language.



Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 
The following users thanked this post: hans

Offline glarsson

  • Frequent Contributor
  • **
  • Posts: 814
  • Country: se
Re: An 'interesting' thing you can do in C++
« Reply #113 on: September 13, 2018, 08:55:02 am »
I too am with Bruce Holt. "a = a++;" is perfectly valid C code.
The 6800 microprocessor had a couple of undefined instructions. Using them invoked undefined behavior. For the earliest revisions of the 6800 one of the consequences of invoking undefined behavior was to enable two  buffers to drive the internal data bus at the same time. The practical consequence was that you had to buy a new 6800 — after the processor had short circuited itself to death.
 
The following users thanked this post: MK14

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1714
  • Country: se
Re: An 'interesting' thing you can do in C++
« Reply #114 on: September 13, 2018, 09:00:17 am »
"a = a++;" is perfectly valid C code.
I sincerely hope my (and anyone else's) physical and financial health will never depend on your code.
Nandemo wa shiranai wa yo, shitteru koto dake.
 
The following users thanked this post: MK14

Online hans

  • Super Contributor
  • ***
  • Posts: 1626
  • Country: nl
Re: An 'interesting' thing you can do in C++
« Reply #115 on: September 13, 2018, 09:06:41 am »
No, that's not nasal demons. After "a=a++;", a will either have the same value as before, or will be incremented by 1. There are no other options. The program will not crash. Your computer will not catch on fire. Demons will not fly out of your nose (or your arse).
Anything can happen.
Only fools think that a=a++; is a reasonable thing to write. I don't know what they thing it will accomplish. A more reasonable, but also sinister, situation is when a and a has different names and are pointers pointing at the same variable. On a supetscalar processor the instructions might then be
  move @a,@b
  add @a,@b,1
with both instructions executing at the same time. When both instructions retire and both attempt to update what a points to (@a) at the same time, the processor will detect this and raise some low level exception. If this happens in your nose transplant then nasal daemons is a reasonable result.

https://en.wikipedia.org/wiki/Hazard_(computer_architecture)#Write_after_write_(WAW)

These hazards are common and it's the job of a CPU architecture engineer. Superscalar processors use register renaming to determine what register values are actually alive at which point, and is free to reorder instructions in order to do so. But aboveall, it will know that the value of 'a' will contain the addition of b+1 in your example, so any future references of 'a' must wait on the ADD instruction and not the MOV.

A compiler will need to output it's result in a sequential set of instructions. There is no concept of "at the same time" here. This is a trick done in hardware to speed up the average execution of typical processor programs.

If you argue that the compiler may arbitrarily choose the order of mov or add ; I think that's ill founded. I don't know of any construct in a programming language that allows you to run code outside of the scope of your function. You could model the ++ operator as a function like:
Code: [Select]
void postinc(int& a) {
  int t = a;
  a++;
  return t;
}
int main(int argc, char** args) {
  argc = postinc(argc);
  return argc;
}

I don't see any reason why a compiler would reorder any of these operations. This program will return the value of argc unmodified.
« Last Edit: September 13, 2018, 09:13:03 am by hans »
 

Offline GeorgeOfTheJungle

  • Super Contributor
  • ***
  • !
  • Posts: 2699
  • Country: tr
Re: An 'interesting' thing you can do in C++
« Reply #116 on: September 13, 2018, 09:07:00 am »
"a = a++;" is perfectly valid C code.
I sincerely hope my (and anyone else's) physical and financial health will never depend on your code.

It's even got a mnemonic: IncrementPerhaps INCPRHPS
« Last Edit: September 13, 2018, 09:09:15 am by GeorgeOfTheJungle »
The further a society drifts from truth, the more it will hate those who speak it.
 
The following users thanked this post: MK14

Offline MK14

  • Super Contributor
  • ***
  • Posts: 4527
  • Country: gb
Re: An 'interesting' thing you can do in C++
« Reply #117 on: September 13, 2018, 09:17:52 am »
It's even got a mnemonic: IncrementPerhaps INCPRHPS

I think on some cpus, it is called MAYBEincA, and on some others it is called DOGkill, or MOTHERgreen.
There is this mysterious one, from China, with the NOSEdemon instruction, HEX code 666.
But I can't understand its develish description.
 

Offline hamster_nzTopic starter

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: An 'interesting' thing you can do in C++
« Reply #118 on: September 13, 2018, 09:43:56 am »
"a = a++;" is perfectly valid C code.
I sincerely hope my (and anyone else's) physical and financial health will never depend on your code.

Um... Sorry, too late  :D. - but I ensured I compared the MD5 hash at both the data at source and destination, just to be sure.

"a = a++;" it is dumb code, stupid code, I hope I never see it in a program, and perhaps an unintentional random behavior generator depending on which way the wind blow, but it is valid C code, it will compile, and it will run.

Code: [Select]
$cat pp.c
#include <stdio.h>

int main(int argc, char *argv[])
{
   int a = 5;
   a = a++;
   switch(a) {
     case 5:
        printf("Option 1\n");
        break;
     case 6:
        printf("Option 2\n");
        break;
     default:
        printf("The world has ended\n");
        break;
   }
}
$gcc -o pp pp.c -pedantic -O4
$./pp
Option 1
$

Yes, I know that with -Wall it does generate a warning...
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline hamster_nzTopic starter

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: An 'interesting' thing you can do in C++
« Reply #119 on: September 13, 2018, 09:53:43 am »
No, that's not nasal demons. After "a=a++;", a will either have the same value as before, or will be incremented by 1. There are no other options. The program will not crash. Your computer will not catch on fire. Demons will not fly out of your nose (or your arse).
Anything can happen.
Only fools think that a=a++; is a reasonable thing to write. I don't know what they thing it will accomplish. A more reasonable, but also sinister, situation is when a and a has different names and are pointers pointing at the same variable. On a supetscalar processor the instructions might then be
  move @a,@b
  add @a,@b,1
with both instructions executing at the same time. When both instructions retire and both attempt to update what a points to (@a) at the same time, the processor will detect this and raise some low level exception. If this happens in your nose transplant then nasal daemons is a reasonable result.

https://en.wikipedia.org/wiki/Hazard_(computer_architecture)#Write_after_write_(WAW)

These hazards are common and it's the job of a CPU architecture engineer. Superscalar processors use register renaming to determine what register values are actually alive at which point, and is free to reorder instructions in order to do so. But aboveall, it will know that the value of 'a' will contain the addition of b+1 in your example, so any future references of 'a' must wait on the ADD instruction and not the MOV.

A compiler will need to output it's result in a sequential set of instructions. There is no concept of "at the same time" here. This is a trick done in hardware to speed up the average execution of typical processor programs.

If you argue that the compiler may arbitrarily choose the order of mov or add ; I think that's ill founded. I don't know of any construct in a programming language that allows you to run code outside of the scope of your function. You could model the ++ operator as a function like:
Code: [Select]
void postinc(int& a) {
  int t = a;
  a++;
  return t;
}
int main(int argc, char** args) {
  argc = postinc(argc);
  return argc;
}

I don't see any reason why a compiler would reorder any of these operations. This program will return the value of argc unmodified.

It is more that the compiler can chose what machine code to use, and they are not all guaranteed to have identical results - the end result may change depending on the compiler used, the compiler options used and the target architecture. For example, maybe the compiler decides to inline some code, and is then can optimize away the ++ operation....

Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Online hans

  • Super Contributor
  • ***
  • Posts: 1626
  • Country: nl
Re: An 'interesting' thing you can do in C++
« Reply #120 on: September 13, 2018, 10:24:46 am »
Well that's right. A common optimization step in write-after-write hazard is not carry out the first write at all. The first write is useless, as the result gets overwritten anyway without any intermediate use.

So the ++; operation is redundant and can be removed. This is a valid optimization step.
However erroneous behaviour occurs if the compiler or CPU decides to reorder these write instructions, as that will influence the functional behaviour of the program. This is not called undefined behaviour, but a serious bug.

Hence, if you test out every compiler on godbolt.org (or any other compiler explorer you've got) and turn on the optimizer, then I bet all of them will return the incoming value.
Most assembly outputs I've seen do not touch the incoming argument at all with an add instruction, e.g. on x86 all I get is:
Quote
main:                                   # @main
        mov     eax, edi
        ret

And also no warnings or errors, by the way, with -Werror -Wall turned on. Even if the program is written as:
Quote
int main(int argc, char** args) {
    int* p = &argc;
    *p = argc++;
    return argc;
}
 

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1714
  • Country: se
Re: An 'interesting' thing you can do in C++
« Reply #121 on: September 13, 2018, 10:52:04 am »
This program will return the value of argc unmodified.
That program does not exhibit undefined behaviour, so I don't understand your point: you've just provided a possible, naïve, implementation. :-//
But, in general, a compiler is free to reorder operations as it likes (even across SPs, if no volatile object is involved), as long as the abstract machine shows the same behaviour it would have had before the reordering.
For UB, this last constraint is voided. :horse:

Quote
The result was that a block local variable would keep its random uninitialized value.

If a was uninitialized before that line, it would have to remain so after it, so that's ok, isn't it?
IIRC, it was along the lines of y[n] = z[n++], with 'y' a local array.
It was definitely not OK...

Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline dmills

  • Super Contributor
  • ***
  • Posts: 2093
  • Country: gb
Re: An 'interesting' thing you can do in C++
« Reply #122 on: September 13, 2018, 11:17:02 am »
That one is fairly classic, the other good one is that if you do a pointer null check after dereferencing the pointer the compiler is free to take the fact that you have dereferenced the pointer as guaranteeing that the pointer is non null.

x=p->foo;
if (p == NULL){...... // This block will be removed as dead code because the dereference above says that p cannot be null without involving UB.

Yes, the null check was in the wrong place, but the some of the security types still got sniffy when this behaviour was introduced.

Regards, Dan.

 
The following users thanked this post: newbrain

Online hans

  • Super Contributor
  • ***
  • Posts: 1626
  • Country: nl
Re: An 'interesting' thing you can do in C++
« Reply #123 on: September 13, 2018, 11:30:44 am »
This program will return the value of argc unmodified.
That program does not exhibit undefined behaviour, so I don't understand your point: you've just provided a possible, naïve, implementation. :-//
But, in general, a compiler is free to reorder operations as it likes (even across SPs, if no volatile object is involved), as long as the abstract machine shows the same behaviour it would have had before the reordering.
For UB, this last constraint is voided. :horse:

Quote
The result was that a block local variable would keep its random uninitialized value.

If a was uninitialized before that line, it would have to remain so after it, so that's ok, isn't it?
IIRC, it was along the lines of y[n] = z[n++], with 'y' a local array.
It was definitely not OK...

Because: https://en.cppreference.com/w/cpp/language/eval_order#Undefined_behavior_2

I'm bringing this point up because people seem not to understand what language specifications are.

I agree, UB happens in the circumstances that you describe. But in the example of "a=a++" that doesn't need to happen.
 

Offline glarsson

  • Frequent Contributor
  • **
  • Posts: 814
  • Country: se
Re: An 'interesting' thing you can do in C++
« Reply #124 on: September 13, 2018, 11:49:04 am »
So the ++; operation is redundant and can be removed. This is a valid optimization step.
Unless the variable is declared volatile, then "both" writes must happen.

But then again, if you invoke undefined behavior anything can happen.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf