Note: Forums will be making significant UX changes to address key usability improvements surrounding search, discoverability and navigation. To learn more about these changes please visit the announcement which can be found HERE.
Simple C Program - Failing in a particular scenario

Answered Simple C Program - Failing in a particular scenario

  • Thursday, March 08, 2012 9:00 PM
     
     

    Hi guys,

    Looks at this simple C Code.


    #include <stdio.h>
    #include <stdlib.h>
    int main(void)
    {
        int k;
        int ctr = 0;
        for (k = 0; k < 5; k++)
        {
            if ( k == 0 )
            {
                printf("\n----------");
            }
            ctr++;
        }
        printf("\n Counter is supposed to be 5. But the Value is  = %d ",ctr);
        puts("\n End of K Loop");
        return 0;
    }

    I believe that this program should print the counter value as 5. But it prints the value as 1. Any Idea why is this so?

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    But this works,

    int main(void)
    {
        int k;
        int ctr = 0;
        for (k = 0; k < 5; k++)
        {
            if ( k <1 )
            {
                printf("\n----------");
            }
            ctr++;
        }
        printf("\n Counter is supposed to be 5. But the Value is  = %d ",ctr);
        puts("\n End of K Loop");
        return 0;
    }

    ~~~~~~~~~~~~~~~~~~~

    This also works

    int main(void)
    {
        int k;
        int ctr = 0;

        int dum=0;

        for (k = 0; k < 5; k++)
        {
            if ( k == 0 )
            {
                dum=0;
            }
            ctr++;
        }
        printf("\n Counter is supposed to be 5. But the Value is  = %d ",ctr);
        puts("\n End of K Loop");
        return 0;
    }

    Any clues? This happens in Visual Studio 2008 SP1.

    Thanks,

    Vasanth

All Replies

  • Thursday, March 08, 2012 9:08 PM
     
     Answered

    On 3/8/2012 4:00 PM, Vasanth Sivanatarajan wrote:

    #include<stdio.h>
    #include<stdlib.h>
    int main(void)
    {
         int k;
         int ctr = 0;
         for (k = 0; k<  5; k++)
         {
             if ( k == 0 )
             {
                 printf("\n----------");
             }
             ctr++;
         }
         printf("\n Counter is supposed to be 5. But the Value is  = %d ",ctr);
         puts("\n End of K Loop");
         return 0;
    }

    I believe that this program should print the counter value as 5. But it prints the value as 1. Any Idea why is this so?

    Prints 5 for me. Can't reproduce - working as expected.


    Igor Tandetnik

  • Thursday, March 08, 2012 9:21 PM
     
     
    It's an optimization issue which will manifest when a
    Release Build is done, but not in a Debug build.

    - Wayne
  • Thursday, March 08, 2012 9:23 PM
     
     

    On 3/8/2012 4:21 PM, WayneAKing wrote:

    It's an optimization issue which will manifest when a
    Release Build is done, but not in a Debug build.

    Works as expected in Release, too. Any particular optimization options to trigger the problem?


    Igor Tandetnik

  • Thursday, March 08, 2012 9:31 PM
     
     
    Works as expected in Release, too. Any particular optimization options to trigger the problem?
    The OP is using Visual Studio 2008 SP1. I'm using
    Visual C++ 2008 Express without SP1.

    When a Release Build is done with Optimizations "Disabled"
    or set to "Minimize Size", the correct output of 5 is
    displayed. If built with "Maximize Speed" or "Full
    Optimization" then "1" is shown.

    - Wayne

  • Thursday, March 08, 2012 9:53 PM
     
     

    On 3/8/2012 4:31 PM, WayneAKing wrote:

    Works as expected in Release, too. Any particular optimization options to trigger the problem?

    The OP is using Visual Studio 2008 SP1. I'm using
    Visual C++ 2008 Express without SP1.

    When a Release Build is done with Optimizations "Disabled"
    or set to "Minimize Size", the correct output of 5 is
    displayed. If built with "Maximize Speed" or "Full
    Optimization" then "1" is shown.

    Yes, can reproduce with /O2. Looks very much like a bug. One can file it, though I suspect there isn't much point unless the problem also reproduces with VC10 or, better still, VC11 beta.

    Looking at disassembly, the compiler unrolled the loop entirely, and effectively transformed the code into

    printf("\n----------");
    printf("\n Counter is supposed to be 5. But the Value is  = %d ", 1);

    The constant is wrong, of course.


    Igor Tandetnik

  • Thursday, March 08, 2012 10:58 PM
     
     
    Yes, can reproduce with /O2. Looks very much like a bug. One can file it, though I suspect there isn't much point unless the problem also reproduces with VC10 or, better still, VC11 beta.
    On VC10 it seems even worse. I seem to get the problem in Release build no matter what the optimization settings.
     
    Debug works fine.
     

    David Wilkinson | Visual C++ MVP
  • Friday, March 09, 2012 12:05 AM
     
     

    Hi Guys,

    Thanks for the observations.

    This segment of code was in a production program and it was working for years, which was initially compiled in VC 2005. As per the end application requirement, we had to move to VC 2008 and something weird happened. Finally, we found this issue. You are correct, this happens in Release Mode and not in Debug Mode.

    I understand that it's related to Optimization. But we were thinking that this might be happening whenever we use == in a IF condition. Is that true? If yes, we are scared that lot many other programs that are in production, may fail too now, as all were recompiled in VS 2008. In a year, we would be moving to VS 2010, as per the end application requirement.

    What action can we take at this point?

    Thanks,

    Vasanth Sivanatarajan

  • Friday, March 09, 2012 12:13 AM
     
     

    On 3/8/2012 7:05 PM, Vasanth Sivanatarajan wrote:

    This segment of code was in a production program

    I wonder why you've written your code this way in the first place. What's the purpose of the loop? It's equivalent to

    int ctr = 5;
    printf("\n----------");

    I understand that it's related to Optimization. But we were thinking that this might be happening whenever we use == in a IF condition. Is that true?

    That's highly unlikely. It would have broken millions of lines of code, and couldn't possibly have gone unnoticed for so long.

    The problem appears to be triggered by a trivial loop in your code, that the optimizer decided it could eliminate, but didn't quite do that correctly. One way to avoid this is to not write trivial loops.


    Igor Tandetnik

  • Friday, March 09, 2012 1:26 AM
     
     

    Hi,

    This code was written by my friend few years ago. He reads multiple data files, each one of which will have thousands of lines(Each line contains several double values).

    In one particular function, he has three level nested loops. In the inner most loop (say K loop), he has condition that certain things has to be done only for the first item of K loop by saying IF (K == 0). In the actual production code, instead of executing this segment only one time, it got executed for all the K values. Inside the If condition, he has assigned values for a double ** (previously allocated memory with dynamic allocation). We did check the memory, leaks etc.,

    He pulled out a simple code segment, where he could kind of reproduce the problem. I understand, the simple code that I had pasted first, might look weird but that was written just to show one of the problem.

    For now, we could disable the Optimization and also change the condition to IF (K < 1).

    Thanks,

    Vasanth

  • Friday, March 09, 2012 1:38 AM
     
     

    On 3/8/2012 8:26 PM, Vasanth Sivanatarajan wrote:

    In one particular function, he has three level nested loops. In the
    inner most loop (say K loop), he has condition that certain things
    has to be done only for the first item of K loop by saying IF (K ==
    0). In the actual production code, instead of executing this segment
    only one time, it got executed for all the K values. Inside the If
    condition, he has assigned values for a double ** (previously
    allocated memory with dynamic allocation). We did check the memory,
    leaks etc.,

    For now, we could disable the Optimization and also change the condition to IF (K<  1).

    Why not remove this inner loop entirely? If you only need to exectute a piece of code one time, why do you put it in a loop at all? The very fact that you have this issue demonstrates that the loop isn't actually needed (since the optimizer attempted to eliminate it, albeit unsuccessfully).


    Igor Tandetnik

  • Friday, March 09, 2012 1:45 AM
     
     

    Yes. I need to check with him. If that's the only thing he does inside the third loop, then obviously it makes sense to remove that loop. If not, we will see if there's a way to reorganize this.

    Thanks,

    Vasanth

  • Friday, March 09, 2012 4:58 AM
     
      Has Code
    he has condition that certain things has to be done only for the first item of K loop by saying IF (K == 0).
    Why he need a loop here. He can check the condition for first value directly. This is the infamous for-if anti-pattern see http://blogs.msdn.com/b/oldnewthing/archive/2011/12/27/10251210.aspx
  • Friday, March 23, 2012 1:28 PM
     
     

    This is fixed in VS11. Here is the message,

    Greetings from Microsoft Connect!

    This notification was generated for feedback item: <a href="http://connect.microsoft.com/VisualStudio/feedback/details/729818/for-loop-error">For loop Error</a> which you submitted at the <a href="http://connect.microsoft.com">Microsoft Connect</a> site.

    Hi, thanks for this report. This is a bug in the optimizer, and will be fixed in the release of VS11. If you are curious, here are the details.

    There is an optimization called if-unswitching that turns:

    for (i=L; i<U; i++) {
      if (i == 3)
         // do something
    }

    Into this (removing the for-loop entirely):

    if (L <= 3 < U) {
      i=3;
      // do something
    }

    The bug is that we were not considering uses of 'i' beyond the loop body when performing if-unswitching. This will be fixed in VS11.

    Thanks!
    Eric
    Microsoft VC++ Team

    You may receive a general "Feedback Item Updated" notification as well, if any other changes were made by Microsoft.

    Thank you for using Microsoft Connect!

    Regards,

    the Microsoft Connect Team

  • Friday, March 23, 2012 8:09 PM
     
     
    Vasanth -

    Thanks for submitting it to MS and for posting the
    result here.

    To avoid possible confusion for new readers of this thread,
    I suggest that you UNmark as "Answer" the reply from Igor
    which stated: "Can't reproduce - working as expected."
    and mark your last post with the official reply from
    Microsoft Connect confirming an optimizer bug as
    the "Answer".

    - Wayne