Simple Trick to Detect Integer Overflow (C/C++)

The performance impact is noticeable
NwF8je - Online C++0x Compiler & Debugging Tool - Ideone.com (with)
l2fSzm - Online C++0x Compiler & Debugging Tool - Ideone.com (without)

9 Likes

Great - thanks for doing the experiment and providing some hard numbers :slight_smile:

1 Like

I’m trying to use the

#pragma GCC optimize "trapv"

But when i use the following code

#pragma GCC optimize "trapv"
#include<iostream>
#include<bits/stdc++.h>
#define ll long long int
using namespace std;
int main(){
        int a=10000000,b=1000000000;
        cout<<a<<" "<<b<<'\n';
        int f=a*b;
        cout<<f;
}

It’s not crashing. How do I use it correctly?

1 Like

Interesting - it’s not crashing for me, either. However:

[simon@simon-laptop][17:53:24]
[~/devel/hackerrank/otherpeoples]>cat everule1-ftrapv-test.cpp 
#pragma GCC optimize "trapv"
#include<iostream>
#include<bits/stdc++.h>
#define ll long long int
using namespace std;
int main(){
        int a,b;
        cin >> a >> b;
        cout<<a<<" "<<b<<'\n';
        int f=a*b;
        cout<<f;
}

[simon@simon-laptop][17:53:32]
[~/devel/hackerrank/otherpeoples]>g++ -std=c++14 everule1-ftrapv-test.cpp  -O3
[simon@simon-laptop][17:53:37]
[~/devel/hackerrank/otherpeoples]>echo "10000000 1000000000" | ./a.out
10000000 1000000000
Aborted (core dumped)

crashes as expected.

I’d guess that with the original version, the compiler is computing the result of a * b at compile-time, and so not triggering the runtime error.

2 Likes

Okay thanks, I thought i was using it incorrectly.

1 Like

Is it safe to submit with this optimization? I read someplace that this increases runtime. Increased runtime is fine as long as it don’t give TLE.

1 Like

Simple Trick to Detect Integer Overflow (C/C++) - #16 by rahul_g :slight_smile:

3 Likes

What do you guys use for a long long infinity?
I generally use int INF = 987654321 for an int infinity. This works everytime, but when I used a random INF value for long long infinity, I got a WA. So I ended up using LLONG_MAX, and whenever I did a = b + c, I had to do this instead.

[Random as in not rand(), some random large value]

if(b == LLONG_MAX or c == LLONG_MAX) a = LLONG_MAX
else a = b + c

Having a long long infinity can make this so much simpler.

1e18. You can add without overflows

1 Like

I often use (1<<29) as an infinity value for int, and would probably use something like (1LL<<60) for a long long infinity.

2 Likes

Wow thank you so much such an awesome post.
You deserve 10 likes from each user.

2 Likes

Sadly, there’s a pretty big flaw in it discovered in this thread:

(see the Important Update in the OP) :frowning:

2 Likes

Will need to read about it a bit more. I am sure it will be useful otherwise it won’t be available in the first place. Just need to figure out when and why.

1 Like

Yes, I suppose: I’ve been using it for ages, and this situation is the first I’ve seen where it breaks :man_shrugging:

3 Likes

Can you please. explain where it fails I am not able to get the program

I use certain flag, which gives warning for these type of bugs while compiling.

I think it would be nice if -Wconversion was used more often. In case one is aware of what’s going on, one can always explicitly type-cast and not be warned. :slightly_smiling_face:

-Wconversion

Warn for implicit conversions that may alter a value. This includes conversions between real and integer, like abs (x) when x is double; conversions between signed and unsigned, like unsigned ui = -1; and conversions to smaller types, like sqrtf (M_PI). Do not warn for explicit casts like abs ((int) x) and ui = (unsigned) -1, or if the value is not changed by the conversion like in abs (2.0). Warnings about conversions between signed and unsigned integers can be disabled by using -Wno-sign-conversion.

For C++, also warn for confusing overload resolution for user-defined conversions; and conversions that never use a type conversion operator: conversions to void, the same type, a base class or a reference to them. Warnings about conversions between signed and unsigned integers are disabled by default in C++ unless -Wsign-conversion is explicitly enabled.

Warnings about conversion from arithmetic on a small type back to that type are only given with -Warith-conversion.

1 Like

Ah, yes - it gives a very stern warning for this example:

[simon@simon-laptop][16:20:33]
[~/devel/hackerrank/otherpeoples]>./compile-latest-cpp.sh 
Compiling ftrapv-count-example.cpp
+ g++ -std=c++14 ftrapv-count-example.cpp -O3 -g3 -Wall -Wextra -Wconversion -DONLINE_JUDGE -D_GLIBCXX_DEBUG -fsanitize=undefined -ftrapv
ftrapv-count-example.cpp: In function ‘int main()’:
ftrapv-count-example.cpp:14:41: warning: conversion to ‘int’ from ‘long long int’ may alter its value [-Wconversion]
     tooSmallToStoreResultIfXIsMoreThan2 *= x;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
+ set +x
Successful

I haven’t found a clang flag that makes it warn about this particular issue, yet, but I did find one that detects it at runtime:

[simon@simon-laptop][16:20:36]
[~/devel/hackerrank/otherpeoples]>./compile-latest-cpp.sh clang
clang
Compiling ftrapv-count-example.cpp
+ clang++ -std=c++14 -stdlib=libc++ ftrapv-count-example.cpp -O3 -g3 -Wall -Wextra -Wconversion -DONLINE_JUDGE -D_LIBCPP_DEBUG=1 -L/home/simon/tmp/DONTSYNC/clang-git/install/lib/ -fsanitize=undefined,bounds,integer -ftrapv
ftrapv-count-example.cpp:1:13: warning: unknown pragma ignored [-Wunknown-pragmas]
#pragma GCC optimize "trapv"
            ^
1 warning generated.
+ set +x
Successful
[simon@simon-laptop][16:21:55]
[~/devel/hackerrank/otherpeoples]>echo "3" | ./a.out 
ftrapv-count-example.cpp:14:41: runtime error: implicit conversion from type 'long long' of value 3000000000 (64-bit, signed) to type 'int' changed the value to -1294967296 (32-bit, signed)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior ftrapv-count-example.cpp:14:41 in 
x: 3 tooSmallToStoreResultIfXIsMoreThan2:-1294967296
1 Like

or use clang++ :upside_down_face:

I personally use this, may be this will help.
Sanitizers are great to prevent such situations.
g++ file.cpp -Wall -Werror -std=c++17 -fsanitize=address -fsanitize=leak -fsanitize=undefined -fsanitize=null -fsanitize=vla-bound -fsanitize=return -fsanitize=bounds -g

3 Likes