19

I've implemented some sorting algorithms (to sort integers) in C, carefully using uint64_t to store anything which has got to do with the data size (thus also counters and stuff), since the algorithms should be tested also with data sets of several giga of integers.

The algorithms should be fine, and there should be no problems about the amount of data allocated: data is stored on files, and we only load little chunks per time, everything works fine even when we choke the in-memory buffers to any size.

Tests with datasets up to 4 giga ints (thus 16GB of data) work fine (sorting 4Gint took 2228 seconds, ~37 minutes), but when we go above that (ie: 8 Gints) the algorithm doesn't seem to halt (it's been running for about 16 hours now).

I'm afraid the problem could be due to integer overflow, maybe a counter in a loop is stored on a 32 bits variable, or maybe we're calling some functions that works with 32 bits integers.
What else could it be?

Is there any easy way to check whether an integer overflow occurs at runtime?

Alex Z
  • 1,867
  • 1
  • 29
  • 27
peoro
  • 25,562
  • 20
  • 98
  • 150
  • You might be interested in the answers given for: http://stackoverflow.com/questions/199333/best-way-to-detect-integer-overflow-in-c-c – Flexo Feb 15 '11 at 15:20
  • @awoodland: uh, couldn't find that post. It seems to focus on letting the program handle overflows (while in my case I need to avoid them and thus see where/why they happen), but contains lots of useful answers! – peoro Feb 15 '11 at 15:50
  • Try check code by Viva64 tool - http://www.viva64.com/en/viva64-tool/ –  Feb 18 '11 at 11:50
  • Good tool but it is Windows-only – Alex Z Apr 18 '12 at 16:56

5 Answers5

19

This is compiler-specific, but if you're using gcc then you can compile with -ftrapv to issue SIGABRT when signed integral overflow occurs.

For example:

/* compile with gcc -ftrapv <filename> */
#include <signal.h>
#include <stdio.h>
#include <limits.h>

void signalHandler(int sig) {
  printf("Overflow detected\n");
}

int main() {
  signal(SIGABRT, &signalHandler);

  int largeInt = INT_MAX;
  int normalInt = 42;
  int overflowInt = largeInt + normalInt;  /* should cause overflow */

  /* if compiling with -ftrapv, we shouldn't get here */
  return 0;
}

When I run this code locally, the output is

Overflow detected
Aborted
Nate Kohl
  • 35,264
  • 10
  • 43
  • 55
  • 1
    this is **exactly** what I was looking for! Your sample works on my machine, gonna try this with the sorting algorithm and will let you know if it worked `:-)` – peoro Feb 15 '11 at 15:47
  • That was what I was getting at with the thread I linked too, but I missed -ftrapv raising SIGABRT instead of SIGFPE. – Flexo Feb 15 '11 at 16:20
  • 1
    great but acording to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19020 and my simple test on 64b gcc 4.5.2 -ftrapv is not working – teZeriusz Apr 21 '11 at 16:14
  • It failed for me also, with gcc 4.5.2 on amd64. – nibot Oct 17 '12 at 20:10
  • 1
    42 is Internet's favourite number. :-p – Constantino Tsarouhas Jan 25 '13 at 02:04
  • On my Mac it is `SIGILL` instead of `SIGABRT`. In addition, the handler will be called again and again, so I think I should `abort()` within it. – Franklin Yu Jan 04 '17 at 10:38
14

Take a look at -ftrapv and -fwrapv:

-ftrapv

This option generates traps for signed overflow on addition, subtraction, multiplication operations.

-fwrapv

This option instructs the compiler to assume that signed arithmetic overflow of addition, subtraction and multiplication wraps around using twos-complement representation. This flag enables some optimizations and disables other. This option is enabled by default for the Java front-end, as required by the Java language specification.

See also Integer overflow in C: standards and compilers, and Useful GCC flags for C.

Community
  • 1
  • 1
Matt Joiner
  • 112,946
  • 110
  • 377
  • 526
2

clang now support dynamic overflow checks for both signed and unsigned integers. See -fsanitize=integer switch. For now it is only one C++ compiler with fully supported dynamic overflow checking for debug purpose.

ZAB
  • 963
  • 10
  • 18
  • 1
    It's -fsanitize=unsigned-integer-overflow, see: http://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#availablle-checks (Might have changed since the comment) –  Feb 27 '16 at 11:56
  • @DisplayName **integer** turns on all integer checks. It also enable **unsigned-integer-overflow** as well as **signed-integer-overflow** and some others – ZAB Feb 28 '16 at 13:46
1

If you are using Microsoft's compiler, there are options to generate code that triggers a SEH exception when an integer conversion cuts off non-zero bits. In places where this is actually desired, use a bitwise AND to remove the upper bits before doing the conversion.

Simon Richter
  • 28,572
  • 1
  • 42
  • 64
0

The only sure fire way is to wrap operations on those integers into functions that perform bounds violation checking. This will of course slow down integer ops, but if your code asserts or halts on a boundary violation with a meaningful error message, that will go a long way towards helping you identify where the problem is.

As for your particular issue, keep in mind that general case sorting is O(nlogn), so the reason the algorithm is taking much longer could be due to the fact that the increase in time is not linear with respect to the data set size. Since also didn't mention how much physical memory is in the box and how much of it is used for your algorithm, there could possibly be page faulting to disk with the larger data set, thus potentially slowing things to a crawl.

Michael Goldshteyn
  • 71,784
  • 24
  • 131
  • 181
  • I cannot replace any single operation (even any `+`!): that would mean rewriting anything. Moreover I don't know where the problem is: I need to check what's going on just to find out what's going on, won't need to do this kind of checking once the issue is fixed. I risk to forgot to wrap some operations in this work, so I'm not gonna do that.. – peoro Feb 15 '11 at 15:33