-4

I just found a pretty fun code. GCC optimizations change its behavior weirdly.

  • -O0 works
  • -O1 segfault
  • -O2 infinite loop (from 7 to 1996 inclusive)
  • -O3 works
  • -Og segfault
  • -Ofast works

Here's the code :

int main(int argc, char *argv[])
{
  int i, c;

  c = 0;
  for (i = 10; i < 10000; ++i)
    {
      if (is_lychrel(i))
        ++c;

      printf("%d\n", i);
    }

  printf("%d\n", c);

  return EXIT_SUCCESS;
}

The function is_lychrel(int) makes use of the parameter.

As far as I know, this is probably due to an undefined behavior somewhere but I can't spot it. I tried to disable some optimization flags, but I had no luck so far.

If you need more code, feel free to ask.

EDIT: As suggested in the comments, I tried to comment some functions and finally debugged the old school way (because gdb won't work). And I found the culprit (of the segfault at least) :

void add_reverse(int d[], int *len)
{
  int i;
  int plus[28] = {0};

  for (i = 0; i < *len; ++i)
    {
      //printf("d %d\n", i);

      plus[i] = d[*len - i - 1];
    }

  add(d, plus, len);
}

This function is assumed to add a number (as an array of digits) to his reverse and return the new length. Exemple: ({1, 2}, 2) should give ({3, 3}, 2). It doesn't segfault with the printf but won't give the good result. I'm trying to analyze d[] step by step. d[] is 0034647260072070369072646341 just before segfault (seems valid).

EDIT 2: Adding a simple displaying loop (diplay one won't be enough) after computation of plus correct the output of -O1.

  for (i = 0; i < *len; ++i)
    printf("%d", plus[i]);

Here's add() code if ever that could help:

void add(int d[], int plus[], int *maxlen)
{
  int i, of;

  of = 0;
  for (i = 0; i <= *maxlen; ++i)
    {
      d[i] += plus[i];

      if (of)
        {
          d[i] += of;
          of    = 0;
        }

      if (d[i] >= 10)
        {
          of    = 1;
          d[i] %= 10;
        }
    }

  if (d[i - 1])
    ++*maxlen;
}
kiwixz
  • 1,380
  • 15
  • 23
  • 1
    Maybe related to [Function optimized to infinite loop at 'gcc -O2'](http://stackoverflow.com/q/28631378/1708801) – Shafik Yaghmour Mar 11 '15 at 16:50
  • 4
    We need the implementation of `is_lychrel()`. – timrau Mar 11 '15 at 16:50
  • 2
    You suspect of undefined but you didn't post `is_lychrel()` which is the only thing in the code that could be doing something bad. – Iharob Al Asimi Mar 11 '15 at 16:50
  • That code is pretty "vanilla" and `is_lychrel` could be doing something bad. Try replacing `is_lychrel` with something other very simple function and see if you still get a segfault. My guess is that you won't. – lurker Mar 11 '15 at 16:51
  • 2
    Remove `is_lychrel(i)` from your code. if the problem no longer represents (and I cannot fathom how it still could), guess where the UB is? – WhozCraig Mar 11 '15 at 16:53
  • 1
    Does the real code also miss to `#include` anything? – alk Mar 11 '15 at 16:55

1 Answers1

0

Simple. My arrays were too small. I was sure of the size for some reason but I was definitely wrong. I should've checked that first.

Every optimization level works fine now.

kiwixz
  • 1,380
  • 15
  • 23