title: gcc optimization gives infinite loop or segfault
body: <p>I just found a pretty fun code. GCC optimizations change its behavior weirdly.</p>
  
  <ul>
  <li>-O0 works</li>
  <li>-O1 segfault</li>
  <li>-O2 infinite loop (from 7 to 1996 inclusive)</li>
  <li>-O3 works</li>
  <li>-Og segfault</li>
  <li>-Ofast works</li>
  </ul>
  
  <p>Here's the code :</p>
  
  <pre><code>int main(int argc, char *argv[])
  {
    int i, c;
  
    c = 0;
    for (i = 10; i &lt; 10000; ++i)
      {
        if (is_lychrel(i))
          ++c;
  
        printf("%d\n", i);
      }
  
    printf("%d\n", c);
  
    return EXIT_SUCCESS;
  }
  </code></pre>
  
  <p>The function <code>is_lychrel(int)</code> makes use of the parameter.</p>
  
  <p>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.</p>
  
  <p>If you need more code, feel free to ask.</p>
  
  <p><strong>EDIT:</strong>
  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) :</p>
  
  <pre><code>void add_reverse(int d[], int *len)
  {
    int i;
    int plus[28] = {0};
  
    for (i = 0; i &lt; *len; ++i)
      {
        //printf("d %d\n", i);
  
        plus[i] = d[*len - i - 1];
      }
  
    add(d, plus, len);
  }
  </code></pre>
  
  <p>This function is assumed to add a number (as an array of digits) to his reverse and return the new length. Exemple: <code>({1, 2}, 2)</code> should give <code>({3, 3}, 2)</code>. It doesn't segfault with the <code>printf</code> but won't give the good result. I'm trying to analyze d[] step by step. d[] is <code>0034647260072070369072646341</code> just before segfault (seems valid).</p>
  
  <p><strong>EDIT 2:</strong>
  Adding a simple displaying loop (diplay one won't be enough) after computation of <code>plus</code> correct the output of <strong>-O1</strong>.</p>
  
  <pre><code>  for (i = 0; i &lt; *len; ++i)
      printf("%d", plus[i]);
  </code></pre>
  
  <p>Here's <code>add()</code> code if ever that could help:</p>
  
  <pre><code>void add(int d[], int plus[], int *maxlen)
  {
    int i, of;
  
    of = 0;
    for (i = 0; i &lt;= *maxlen; ++i)
      {
        d[i] += plus[i];
  
        if (of)
          {
            d[i] += of;
            of    = 0;
          }
  
        if (d[i] &gt;= 10)
          {
            of    = 1;
            d[i] %= 10;
          }
      }
  
    if (d[i - 1])
      ++*maxlen;
  }
  </code></pre>