Discussion:
Compiler warnings, overflow
Ricardo Telichevesky
2014-07-31 17:00:51 UTC
Permalink
Hi, hope this is the right list.

Here is my code and output, at the bottom of the e-mail. y is "correct", w and z obviously have problems - multiplying two 32-bit integers "hoping" the result would be correct assigning to 64-bit - I guess it is the same problem as double oneThird= 1/3; the result being zero, and not 0.3333.

I was wondering if there is any strict warning that would flag the w and z assignments below, or the 1/3 above - the whole right hand side is evaluated as a 32-bit integer number, and assigned to a 64-bit integer or double. Not advocating this should be a default, but turning it on would help me
detect some flaws in the code. Took me hours to catch a similar bug in my code, trying to solve a sparse system that has hundreds of millions of variables...

Thanks!
Ricardo

laplace utils % cat ovr.c
#include <stdio.h>
int main()
{

unsigned int x = 1015625426;
unsigned int t = sizeof(double);

size_t y = x * sizeof(double);
size_t w = x << 3;
size_t z = x * t;

printf("y= %zd w = %zd z = %zd\n", y, w, z);
}
laplace utils % gcc -Wall -o ovr ovr.c
laplace utils % ovr
y= 8125003408 w = 3830036112 z = 3830036112
Andrew Haley
2014-07-31 17:12:01 UTC
Permalink
Post by Ricardo Telichevesky
Hi, hope this is the right list.
Here is my code and output, at the bottom of the e-mail. y is
"correct", w and z obviously have problems - multiplying two 32-bit
integers "hoping" the result would be correct assigning to 64-bit -
I guess it is the same problem as double oneThird= 1/3; the result
being zero, and not 0.3333.
I was wondering if there is any strict warning that would flag the w
and z assignments below, or the 1/3 above - the whole right hand
side is evaluated as a 32-bit integer number, and assigned to a
64-bit integer or double. Not advocating this should be a default,
but turning it on would help me detect some flaws in the code. Took
me hours to catch a similar bug in my code, trying to solve a sparse
system that has hundreds of millions of variables...
To quote the standard:

"A computation involving unsigned operands can never overflow, because
a result that cannot be represented by the resulting unsigned integer
type is reduced modulo the number that is one greater than the largest
value that can be represented by the resulting type."

So, from C's point of view there is nothing to warn about.

Andrew.
Manuel López-Ibáñez
2014-07-31 17:52:45 UTC
Permalink
Post by Ricardo Telichevesky
Hi, hope this is the right list.
Here is my code and output, at the bottom of the e-mail. y is "correct", w
and z obviously have problems - multiplying two 32-bit integers "hoping" the
result would be correct assigning to 64-bit - I guess it is the same problem
as double oneThird= 1/3; the result being zero, and not 0.3333.
I think this is https://gcc.gnu.org/bugzilla/show_bug.cgi?id=42935

But unfortunately, we have too many bugs/enhancements to fix and too
few people to work on them, so I would not expect to get this one
fixed soon.

If you have some free time (or someone with programming skills that
you can convince/pay), I think it should not be very hard to implement
(only time consuming), but the devil is in the details.

Cheers,

Manuel.
David Brown
2014-08-01 08:53:41 UTC
Permalink
Post by Ricardo Telichevesky
Hi, hope this is the right list.
Here is my code and output, at the bottom of the e-mail. y is "correct",
w and z obviously have problems - multiplying two 32-bit integers
"hoping" the result would be correct assigning to 64-bit - I guess it is
the same problem as double oneThird= 1/3; the result being zero, and
not 0.3333.
I was wondering if there is any strict warning that would flag the w and
z assignments below, or the 1/3 above - the whole right hand side is
evaluated as a 32-bit integer number, and assigned to a 64-bit integer
or double. Not advocating this should be a default, but turning it on
would help me detect some flaws in the code. Took me hours to catch a
similar bug in my code, trying to solve a sparse system that has
hundreds of millions of variables...
Thanks!
Ricardo
laplace utils % cat ovr.c
#include <stdio.h>
int main()
{
unsigned int x = 1015625426;
unsigned int t = sizeof(double);
size_t y = x * sizeof(double);
size_t w = x << 3;
size_t z = x * t;
printf("y= %zd w = %zd z = %zd\n", y, w, z);
}
laplace utils % gcc -Wall -o ovr ovr.c
laplace utils % ovr
y= 8125003408 w = 3830036112 z = 3830036112
Hi,

As others have said, it's not easy to warn about this sort of thing
since it is perfectly valid C - and many programs rely on the overflow
behaviour of unsigned integers.

But as a stylistic point, you should probably avoid using types like
"unsigned int" and "size_t" when you are concerned about integer sizes -
it is far safer, clearer, and more portable to use the size-specific
types in <stdint.h> such as "uint32_t" and "uint64_t". Of course, you
might want to use typedefs to make things even clearer, or to allow you
to easily change the sizes at a later date. But start from the
<stdint.h> types.

Another point is to remember to enable optimisation. It won't help in
this case, but some warnings work better when optimisation (at least
-O1) is enabled. And of course your code will run far faster.

David

Loading...