[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

Code crashes at runtime - is this valid c++

chrisstankevitz

11/6/2008 7:59:00 PM

Compile with:
g++ crash.cpp -O2

Crashes on:
g++ (Gentoo 4.3.2 p1.1) 4.3.2
g++ (GCC) 4.3.0 20080428 (Red Hat 4.3.0-8)
g++ (ubuntu current stable)

Steps to reproduce:
1. Make a file crash.cpp (contents below)
2. g++ crash.cpp -O2
3. ./a.out
Floating point exception

Source:

#include <iostream>
#include <fenv.h>

float g(const float& x)
{
float y = x;
if(y == 0.0f)
{
y=1.0f;
}
return x/y;
}

void f(const float &z)
{
if (z > 0.0f)
{
float Unit2 = g(z);

std::cout << Unit2;
}
}

int main()
{
feenableexcept(FE_INVALID);

float a = 130.0f;
f(a);

return 0;
}
15 Answers

Rolf Magnus

11/6/2008 8:39:00 PM

0

chrisstankevitz@gmail.com wrote:

> Compile with:
> g++ crash.cpp -O2
>
> Crashes on:
> g++ (Gentoo 4.3.2 p1.1) 4.3.2
> g++ (GCC) 4.3.0 20080428 (Red Hat 4.3.0-8)
> g++ (ubuntu current stable)

Doesn't crash here with:
g++ (Ubuntu 4.3.2-1ubuntu11) 4.3.2


> Steps to reproduce:
> 1. Make a file crash.cpp (contents below)
> 2. g++ crash.cpp -O2
> 3. ./a.out
> Floating point exception

It prints '1' here, which is what I would have expected.

> Source:
>
> #include <iostream>
> #include <fenv.h>
>
> float g(const float& x)
> {
> float y = x;
> if(y == 0.0f)
> {
> y=1.0f;
> }
> return x/y;
> }
>
> void f(const float &z)
> {
> if (z > 0.0f)
> {
> float Unit2 = g(z);
>
> std::cout << Unit2;
> }
> }
>
> int main()
> {
> feenableexcept(FE_INVALID);
>
> float a = 130.0f;
> f(a);
>
> return 0;
> }

Pawel Dziepak

11/6/2008 8:45:00 PM

0

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Rolf Magnus wrote:
> chrisstankevitz@gmail.com wrote:
>
>> Compile with:
>> g++ crash.cpp -O2
>>
>> Crashes on:
>> g++ (Gentoo 4.3.2 p1.1) 4.3.2
>> g++ (GCC) 4.3.0 20080428 (Red Hat 4.3.0-8)
>> g++ (ubuntu current stable)
>
> Doesn't crash here with:
> g++ (Ubuntu 4.3.2-1ubuntu11) 4.3.2

On gcc version 4.3.0 20080428 (Red Hat 4.3.0-8) got from Fedora 9
repositories also works correctly.

Pawel Dziepak
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail....

iEYEARECAAYFAkkTV2UACgkQPFW+cUiIHNqDKwCfcaNU4o20I8NJ7qAhH/6ayGfH
73EAoKnn9MmwvG54pHzEwf0mFY1j9NRu
=r1+s
-----END PGP SIGNATURE-----

Salt_Peter

11/6/2008 10:22:00 PM

0

On Nov 6, 2:59 pm, chrisstankev...@gmail.com wrote:
> Compile with:
> g++ crash.cpp -O2
>
> Crashes on:
> g++ (Gentoo 4.3.2 p1.1) 4.3.2
> g++ (GCC) 4.3.0 20080428 (Red Hat 4.3.0-8)
> g++ (ubuntu current stable)
>
> Steps to reproduce:
> 1. Make a file crash.cpp (contents below)
> 2. g++ crash.cpp -O2
> 3. ./a.out
> Floating point exception
>
> Source:
>
> #include <iostream>
> #include <fenv.h>
>
> float g(const float& x)
> {
> float y = x;
> if(y == 0.0f)

Never compare 2 floats for equality.
Apart from the fact that its an intensive operation for a cpu,
the following is expected...

#include <iostream>

int main()
{
float fa(0.0f);
float fb(0.0f);

if( fa == fb)
std::cout << "not equal\n";
else
std::cout << "equal\n";

std::cout << "Press ENTER to EXIT.\n";
std::cin.get();
}

/*
not equal
*/

> {
> y=1.0f;
> }
> return x/y;
>
> }
>
> void f(const float &z)
> {
> if (z > 0.0f)

z might be 0.0000000001f

> {
> float Unit2 = g(z);
>
> std::cout << Unit2;
> }
>
> }
>
> int main()
> {
> feenableexcept(FE_INVALID);
>
> float a = 130.0f;
> f(a);
>
> return 0;
>
> }

Pete Becker

11/6/2008 10:34:00 PM

0

On 2008-11-06 17:22:06 -0500, Salt_Peter <pj_hern@yahoo.com> said:

> On Nov 6, 2:59 pm, chrisstankev...@gmail.com wrote:
>>
>> float g(const float& x)
>> {
>> float y = x;
>> if(y == 0.0f)
>
> Never compare 2 floats for equality.

Seems like a pretty good way to avoid dividing by zero.

> Apart from the fact that its an intensive operation for a cpu,

Um, no. It's nearly trivial.

> the following is expected...
>
> #include <iostream>
>
> int main()
> {
> float fa(0.0f);
> float fb(0.0f);
>
> if( fa == fb)
> std::cout << "not equal\n";
> else
> std::cout << "equal\n";
>
> std::cout << "Press ENTER to EXIT.\n";
> std::cin.get();
> }
>
> /*
> not equal
> */

A standarde-conforming C++ compiler will not produce that result. Both
values are exact, and the comparison is exact.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

chrisstankevitz

11/6/2008 10:37:00 PM

0

On Nov 6, 12:38 pm, Rolf Magnus <ramag...@t-online.de> wrote:
> It prints '1' here, which is what I would have expected.

Peter,

Thanks that's good that it works for you. Did you use the -O2
option? On three distributions it does not work for me: gentoo,
fedora, and ubuntu.

Chris

chrisstankevitz

11/6/2008 10:39:00 PM

0

On Nov 6, 2:22 pm, Salt_Peter <pj_h...@yahoo.com> wrote:
> Never compare 2 floats for equality.

Salt,

1. I agree.

2. Does my code crash with your compiler when compiled with -O2?

Thanks,

Chris

chrisstankevitz

11/6/2008 10:44:00 PM

0


Crashes on:
g++ (Gentoo 4.3.2 p1.1) 4.3.2
g++ (GCC) 4.3.0 20080428 (Red Hat 4.3.0-8)
g++ (Ubuntu 4.3.2-1ubuntu11) 4.3.2 (my machine, but maybe not Rolf's)

Does not crash on:
g++-4.1.2 (GCC) 4.1.2 (Gentoo 4.1.2 p1.1)

I'm trying SVN version of g++ now.

Chris

PS: Rolf, sorry for calling you Peter earlier.

Andrey Tarasevich

11/6/2008 10:55:00 PM

0

Salt_Peter wrote:
>> ...
>> float g(const float& x)
>> {
>> float y = x;
>> if(y == 0.0f)
>
> Never compare 2 floats for equality.

This is a popular _fake_ rule. There are contexts where it is perfectly
valid to compare machine floats for equality. You just need to
understand what you are doing.

> Apart from the fact that its an intensive operation for a cpu,
> the following is expected...
>
> #include <iostream>
>
> int main()
> {
> float fa(0.0f);
> float fb(0.0f);
>
> if( fa == fb)
> std::cout << "not equal\n";
> else
> std::cout << "equal\n";
>
> std::cout << "Press ENTER to EXIT.\n";
> std::cin.get();
> }
>
> /*
> not equal
> */


No, this is not expected. Quite the opposite, the implementation that
produces this result is clearly broken.


--
Best regards,
Andrey Tarasevich

James Kanze

11/7/2008 9:03:00 AM

0

On Nov 6, 11:22 pm, Salt_Peter <pj_h...@yahoo.com> wrote:
> On Nov 6, 2:59 pm, chrisstankev...@gmail.com wrote:
> > Compile with:
> > g++ crash.cpp -O2

> > Crashes on:
> > g++ (Gentoo 4.3.2 p1.1) 4.3.2
> > g++ (GCC) 4.3.0 20080428 (Red Hat 4.3.0-8)
> > g++ (ubuntu current stable)

I can't reproduce it on any of the systems I have available
here. (Solaris on Sparc, with g++ 4.1.0 or Sun CC 5.8; Linux
2.6.9 on Intel, with g++ 4.1.0, and Windows XP with VC++ 14).
Of course, for all but Linux, I had to modify the code to get it
to compile.

> > Steps to reproduce:
> > 1. Make a file crash.cpp (contents below)
> > 2. g++ crash.cpp -O2
> > 3. ./a.out
> > Floating point exception

> > Source:

> > #include <iostream>
> > #include <fenv.h>

This header is not standard C++, and is only available if you
have C99 as well. (Which means that I would normally expect it
pretty much everywhere---but my expectations are disappointed;
it's present neither under Solaris nor Windows.)

> > float g(const float& x)
> > {
> > float y = x;
> > if(y == 0.0f)

> Never compare 2 floats for equality.

Which is very poor advice. In this particular case, comparison
for equality is exactly what he wants.

> Apart from the fact that its an intensive operation for a cpu,

Since when? It's as fast as any other comparison, integral or
floating point, on the machines available to me.

> the following is expected...

> #include <iostream>

> int main()
> {
> float fa(0.0f);
> float fb(0.0f);

> if( fa == fb)
> std::cout << "not equal\n";
> else
> std::cout << "equal\n";

> std::cout << "Press ENTER to EXIT.\n";
> std::cin.get();
> }

> /*
> not equal
> */

Are you kidding? Any compiler which outputs "not equal" with
that program is seriously broken.

> > {
> > y=1.0f;
> > }
> > return x/y;

> > }
>
> > void f(const float &z)
> > {
> > if (z > 0.0f)

> z might be 0.0000000001f

And z might be -0.000000001f. Or 1e30. Or anything else. The
whole point is that he doesn't know, and that he doesn't want to
divide by zero. The only correct test is thus:

if ( z != 0.0F )

Anything else is a programming error, and shows a complete lack
of understanding of how machine floating point works.

Note that in his actual code, the function is only called with z
equal 130.0. Which can't be 0.0, anyway you cut it, and will
always be greater than 0.0. (For that matter, I don't know of a
machine where it won't be represented exactly.)

> > {
> > float Unit2 = g(z);
> > std::cout << Unit2;
> > }
> > }

> > int main()
> > {
> > feenableexcept(FE_INVALID);
>
> > float a = 130.0f;
> > f(a);
> > return 0;
> > }

For the original poster: does adding the option -ffloat-store
have any effect? G++ isn't fully standards compliant without
it. Not that I think that it could affect your program; all of
the values you use are exactly representable. (It could affect
the program if the value you are comparing with 0.0 is the
result of an expression, and in some strange way, the compiler
picks it up from a register in the comparison, but reloads it
from memory for the division. And the actual real intermediate
results were smaller than 1E-38.) For Intel processors, g++
also accepts -mpc64 and -mpc32, which cause all intermediate
values to be rounded to 64 or 32 bits---this will not only
eliminate excess precision in the intermediate values, but may
also run a little bit faster (particularly on older hardware.

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Thomas J. Gritzan

11/7/2008 2:32:00 PM

0

[about comparing floating point numbers]

James Kanze wrote:
> On Nov 6, 11:22 pm, Salt_Peter <pj_h...@yahoo.com> wrote:
>> the following is expected...
>
>> #include <iostream>
>
>> int main()
>> {
>> float fa(0.0f);
>> float fb(0.0f);
>
>> if( fa == fb)
>> std::cout << "not equal\n";
>> else
>> std::cout << "equal\n";

"==": not equal,
"!=": equal?

I'll case that as typing error. ;-)

>> std::cout << "Press ENTER to EXIT.\n";
>> std::cin.get();
>> }
>
>> /*
>> not equal
>> */
>
> Are you kidding? Any compiler which outputs "not equal" with
> that program is seriously broken.

I disagree. Any compiler outputting "equal" with this program is broken.

But trying to prove something with a wrong program is broken, too.

--
Thomas