While working on a C++ project with Visual C++ Express 2010 I've found an interesting issue that I'd like to understand. The problem is that the result of my program is different if I compile in Debug or Release modes. I made a small program to reproduce it:
#include <stdio.h>
int firstarg(int i)
{
printf("First argument called with i = %d\n", i);
return i;
}
int secondarg(int i)
{
printf("Second argument called with i = %d\n", i);
return i;
}
void function(int i, int j)
{
printf("Function called with %d, %d\n", i,j);
}
int main(int argc, char* argv[])
{
// Line with the problem!
for (int i = 0; i < 5; ) function(firstarg(i), secondarg(i++));
return 0;
}
// Result on RELEASE:
Second argument called with i = 0
First argument called with i = 0
Function called with 0, 0
Second argument called with i = 1
First argument called with i = 1
Function called with 1, 1
Second argument called with i = 2
First argument called with i = 2
Function called with 2, 2
Second argument called with i = 3
First argument called with i = 3
Function called with 3, 3
Second argument called with i = 4
First argument called with i = 4
Function called with 4, 4
// Result on DEBUG
Second argument called with i = 0
First argument called with i = 1
Function called with 1, 0
Second argument called with i = 1
First argument called with i = 2
Function called with 2, 1
Second argument called with i = 2
First argument called with i = 3
Function called with 3, 2
Second argument called with i = 3
First argument called with i = 4
Function called with 4, 3
Second argument called with i = 4
First argument called with i = 5
Function called with 5, 4
As you see, in both cases the second argument is evaluated before the first one (that one I expected, if arguments are processed in some kind of LIFO stack); but in release the increment of the variable i is "optimized away" and delayed until the next iteration of the loop. That was unexpected, and I'd really would like to understand what's going on.
Of course, I can easily "fix" my code by changing the loop to
for (int i = 0; i < 5; ++i) function(firstarg(i+1), secondarg(i));
which will give always the same result regardless of compilation parameters. But, still, what I would really like to understand the reasons behind this optimization of increments.
PS. By the way, I could not reproduce this problem with gcc under linux (Debug with -O0 flag, Release with -O3).