to guru : strange C++ operator behaviour

  • Thread starter Dmitriy Iassenev
  • Start date
D

Dmitriy Iassenev

hi,

I found an interesting thing in operator behaviour in C++ :

int i=1;
printf("%d",i++ + i++);

I think the value of the expression "i++ + i++" _must_ be 3, but all the
compilers I tested print 2.

Then I tried another example

std::vector<int> a;
a.push_back(1);
a.push_back(2);
std::vector<int>::iterator i = a.begin();
printf("%d",*i++ + *i++);

Different compilers print different values : 2 or 3, thought it _must_ be 3.

Possibly, it is because of the compilers C compatibility, since iterators
are C++ construction and their behaviour therefore suits C++ standards,
while for the basic types compilers guarantee C behaviour.

Bjarne Stroustrup wrote in his book that
y = ++x; is equivalent to y = (x+=1);
while
y = x++; is equivalent to y = (t=x,x+=1,t);

Why do all the compilers incorrectly compute the expressions?

Many thanks in advance,
Dmitriy Iassenev.
 
W

WW

Dmitriy said:
hi,

I found an interesting thing in operator behaviour in C++ :

int i=1;
printf("%d",i++ + i++);

I think the value of the expression "i++ + i++" _must_ be 3, but all
the compilers I tested print 2.

You think wrong. The above is undefined behavior. You try to change the
value of a variable more than once with an intervening sequence point. The
compiler is allowed to do whatever it wants, including formatting your
harddisk. Search for sequence point i+++++i on Google. One page is:

http://www.embedded.com/story/OEG20020625S0041
 
H

Howard

int i=1;
printf("%d",i++ + i++);

I think the value of the expression "i++ + i++" _must_ be 3, but all the
compilers I tested print 2.
Bjarne Stroustrup wrote in his book that
y = ++x; is equivalent to y = (x+=1);
while
y = x++; is equivalent to y = (t=x,x+=1,t);

Why do all the compilers incorrectly compute the expressions?

His statement agrees with your test perfectly, doesn't it? You get back 2,
which is 1+1, and after that value is computed, then i gets incremented
(twice). Using his notation,

y = x++ + x++; would be like

y = (t = x+x, x+=1, x+= 1, t);

Right?

-Howard
 
H

Howard

You think wrong. The above is undefined behavior. You try to change the
value of a variable more than once with an intervening sequence point. The
compiler is allowed to do whatever it wants, including formatting your
harddisk. Search for sequence point i+++++i on Google. One page is:

Oh, good point. I forgot about sequence points.

But regardless of what "undefined behavior" means in the standard, you had
best not sell me a compiler that formats my hard drive if I screw up simple
code like this...I know a good lawyer! :)

-Howard
 
F

Fao, Sean

Howard said:
His statement agrees with your test perfectly, doesn't it? You get back 2,
which is 1+1, and after that value is computed, then i gets incremented
(twice). Using his notation,

y = x++ + x++; would be like

y = (t = x+x, x+=1, x+= 1, t);

Right?

Wrong. modifying the same variable twice in the same expression in
undefined so anything could happen.
 
V

Victor Bazarov

Howard said:
His statement agrees with your test perfectly, doesn't it? You get back 2,
which is 1+1, and after that value is computed, then i gets incremented
(twice). Using his notation,

y = x++ + x++; would be like

y = (t = x+x, x+=1, x+= 1, t);

Right?

Nope. Modifying a value of an object twice between sequence points
causes undefined behaviour. Anything is allowed to happen.

The expression (x++ + x++) is NOT like (t = x+x, x+=2) because there
is NO sequence point in the former, whereas in the latter there is
one at the comma.

Victor
 
D

Dmitriy Iassenev

Many thanks to all of you,

I did find an answer in the FAQ that clarified the described situation.

Best regards,
Dmitriy Iassenev.
 
M

Mike Wahler

Howard said:
Oh, good point. I forgot about sequence points.

But regardless of what "undefined behavior" means in the standard, you had
best not sell me a compiler that formats my hard drive if I screw up simple
code like this...I know a good lawyer! :)

So if I sell you a chain saw, and due to your ignorance
you cut off your hand, you'll sue me? I suppose so.
Only in America. :)

-Mike
 
W

WW

Howard said:
Oh, good point. I forgot about sequence points.

But regardless of what "undefined behavior" means in the standard,
you had best not sell me a compiler that formats my hard drive if I
screw up simple code like this...I know a good lawyer! :)

That is outside of the topic of this newsgroup. It belongs to QoI (Quality
of Implementation). ;-)
 
W

WW

Wrong. modifying the same variable twice in the same expression in
undefined so anything could happen.

Yeah. Last time I have tried I have laid an egg and a politician told the
truth on national TV. ;-)
 
M

Mark Kerns

So if I sell you a chain saw, and due to your ignorance
you cut off your hand, you'll sue me?

Of course. First I'd sue you, pay my lawyer, declare bankruptcy, and avoid
your counter-suit. This is America after all.
 
H

Howard

Mike Wahler said:
So if I sell you a chain saw, and due to your ignorance
you cut off your hand, you'll sue me? I suppose so.
Only in America. :)

-Mike

:)

Funny, but a bit ludicrous, Mike. If I buy a chain saw, I know it has the
capability to cut off my hand (or anything else) if I abuse it. After all,
it is DESIGNED to cut things off! However, writing a compiler that
translates the standard's meaing of "undefined behavior" into "I can format
his hard drive if I want" is an act of malice, or at least negligence, and
would definitely be actionable in a court of law (and probably not just in
the US either). Do you write programs that, if the user does not read and
understand your user's manual correctly, will format their hard drive? If
so, please let me know what products you produce so I can avoid them! :)

As a side note, the reason I brought this up is that that statement about
formatting someone's hard drive when undefined behavior is invoked is used
quite often in this newsgroup, but is, in my opinion, very misleading. The
standard may state that a specific type of coding constitutes undefined
behavior under the standard, but that does NOT mean anyone actually writes
compilers that take malicious or bizarre actions under those circumstances.
Compiler writers have customers that must be satisfied, and some (if not
all) of those customers are BOUND to make mistakes sometimes. It is an
imperative that they take at least "reasonable" actions when undefined
behavior is encountered (assuming that they understand and can detect those
conditions in the first place). Failure to do so will lose them customers,
and money, FAST! (Now, if there are any compiler WRITERS out there that
disagree, please let us know. :))

How about, when telling posters about the meaning of "undefined behavior",
we leave it at that, and don't insinuate (or outright state) that they're
going to lose their hard drive if they make a mistake, ok?

-Howard
 
K

Kevin Goodsell

Howard said:
Funny, but a bit ludicrous, Mike. If I buy a chain saw, I know it has the
capability to cut off my hand (or anything else) if I abuse it. After all,
it is DESIGNED to cut things off! However, writing a compiler that
translates the standard's meaing of "undefined behavior" into "I can format
his hard drive if I want" is an act of malice, or at least negligence,

What you apparently fail to realize is that the compiler *cannot* detect
undefined behavior in general, and thus cannot assign behavior to it,
nor can a compiler control what happens in the computer system when a
program attempts to do something it shouldn't. Consider DOS systems with
no memory protection. What happens if you overwrite a random memory area
with a random value? Just about anything is possible, as with undefined
behavior in general.

According to Richard Heathfield in _C Unleashed_, page 68-69:

Nasal Demons

The two most dramatic results of undefined behavior I have personally
witnessed both involved leaving insufficient room in a char array for
the terminating null character of a string.

The first occasion was in 1989, and the victim was my brother, Steve. He
(ahem) drew my attention to his screen, which was displaying a message
asking him to confirm that he wanted to format his hard disk. He was
lucky -- he was asked.

A year or so later, a colleague of mine (hi, Kevin) wasn't quite so
lucky. The first sign of his program's undefined behavior was that his
machine hung. The second sign was that it wouldn't reboot! He had to
spend quite some time nursing the machine back to health using the
diagnostic floppies supplied by the manufacturer.

I've never had anything that bad happen to me. In a way, I've been
fortunate. I would love to bring you a really embarrassing first-hand
account of how I brought down a major government by dereferencing a NULL
pointer or flooded a city by passing (UCHAR_MAX + 1) to isupper(). My
own bugs have been far less dramatic. Sorry to disappoint you.


As a side note, the reason I brought this up is that that statement about
formatting someone's hard drive when undefined behavior is invoked is used
quite often in this newsgroup, but is, in my opinion, very misleading.

It's not even remotely misleading. According to the standard it is
perfectly possible and permissible. Real life is off-topic here (but
note, from the quote above, that this *does* happen in real life).
The
standard may state that a specific type of coding constitutes undefined
behavior under the standard, but that does NOT mean anyone actually writes
compilers that take malicious or bizarre actions under those circumstances.

Never was the claim.
Compiler writers have customers that must be satisfied, and some (if not
all) of those customers are BOUND to make mistakes sometimes. It is an
imperative that they take at least "reasonable" actions when undefined
behavior is encountered (assuming that they understand and can detect those
conditions in the first place).

Which they cannot.
Failure to do so will lose them customers,
and money, FAST! (Now, if there are any compiler WRITERS out there that
disagree, please let us know. :))

How about, when telling posters about the meaning of "undefined behavior",
we leave it at that, and don't insinuate (or outright state) that they're
going to lose their hard drive if they make a mistake, ok?

They could. We shouldn't warn them? They're free to weigh the risk
themselves.

-Kevin
 
H

Howard

What you apparently fail to realize is that the compiler *cannot* detect
undefined behavior in general, and thus cannot assign behavior to it,
nor can a compiler control what happens in the computer system when a
program attempts to do something it shouldn't. under those circumstances. circumstances.

Never was the claim.


I understand your point(s) very well. But look at what I was responding to
again:

It very clearly states the the compler is "allowed" to do whatever it wants.
Well, as I said in my post, a compiler that does "whatever it wants",
especially if it reformats your hard drive because of a coding error, is not
a compiler that will sell very well, because people's hard drives will
ineveitably get reformatted.

-Howard
 
T

tom_usenet

It very clearly states the the compler is "allowed" to do whatever it wants.

And it is! The warranty for a compiler doesn't restrict the effect of
programs that contain bugs, and probably doesn't very much for
programs that don't contain bugs.
Well, as I said in my post, a compiler that does "whatever it wants",
especially if it reformats your hard drive because of a coding error, is not
a compiler that will sell very well, because people's hard drives will
ineveitably get reformatted.

It is unlikely that a bug (read undefined behaviour) will lead to a
hdd reformat, but it has happened, and the compiler isn't to blame,
the code is.

However, the infamous DeathStation 2000 inserts code to reformat your
harddisk if you dereference a null pointer or write off the end of an
array. It hasn't sold well.

Tom
 
K

Kevin Goodsell

Howard said:
I understand your point(s) very well. But look at what I was responding to
again:




It very clearly states the the compler is "allowed" to do whatever it wants.
Well, as I said in my post, a compiler that does "whatever it wants",
especially if it reformats your hard drive because of a coding error, is not
a compiler that will sell very well, because people's hard drives will
ineveitably get reformatted.

Yes, in that context I see your point. Though it's technically correct,
it's a quality-of-implementation issue - and any implementation with
quality that low probably won't sell. But there's a difference between
what the compiler may do (intentionally or unintentionally) and what the
code it generates might do when its behavior is undefined. In the latter
case, even the best compiler can't be expected to detect and safely
handle all instances.

-Kevin
 
D

Default User

It very clearly states the the compler is "allowed" to do whatever it wants.
Well, as I said in my post, a compiler that does "whatever it wants",
especially if it reformats your hard drive because of a coding error, is not
a compiler that will sell very well, because people's hard drives will
ineveitably get reformatted.


You seem to laboring under the misconception that what happens with
undefined behavior is some sort error handler the compiler installed.
That usually is not the case. Most times, you see the reaction of the
runtime environment to the UB.

I'll agree that the compiler doesn't format your hard drive with UB, but
the OS damn well might. Or it may let you scribble over other values,
silently changing them, feeding incorrect values into your nav system
and crashing your millions of dollars space probe. Quite possible, and
quite a bit worse than your formatted hard drive.

The "format your HD" is a useful way to make people think about the
situation. The idea that the system will do something sensible to cover
up your undefined behavior needs to be knocked out of their heads.

"I just used a deleted pointer, and it didn't give me a seg fault like
it's supposed to. Why?"




Brian Rodenborn
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top