static variables not static - possible compiler bug?

static variables not static - possible compiler bug?

I am experiencing a strange regression in my code, if it is compiled with the latest icc 11.1
icc (ICC) 11.1 20090630

The same code worked correctly with previous versions of intel compilers (10.0, 10.1), and works correctly with gcc 4.2.1
The bug with latest icc occurs at all levels of optimization (-O1 ... -O3). I use -mia32 option to support older processors.
I have checked the code for memory overwrites with valgrind, and did not find anything wrong.

Basically, some function variables behave as if they were not static, they are initialised every time the function runs.

The code of the function looks roughly like this:

void myFunction(Widget w, int parameter)
{
 // some variables
 static Widget buttons[2];
 // more variables

 switch (parameter)
  {
   case 0: buttons[0]=w; break;
   case 1: buttons[1]=w; break;
   case 3:
    /* do stuff on buttons, will crash if not initialized */
   break;
  }
}

I find that the value of buttons[0], buttons[1] are always 0 the second time the function is run, even if they are previously correctly initialised.
If I move the variable
static Widget buttons[2];
out of function, in the module header, program works correctly.
I can do this in order to "fix" the program, but I can't program not being sure if "static" will do what it is supposed to do.

Has anybody else experienced any such problems with icc 11.1?
Sorry I can't make a shorter example at the moment, since the program is big and cut&paste of the function won't let you compile it.

9 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Well, yes, moving the data object to where it remains in scope looks like a suitable way of dealing with this, even if you have some interprocedural optimizations enabled, and don't wish to show an example.

I tried the following test case but could not reproduce the issue.

$ cat u67995.cpp
// u6799.cpp
// icc -mia32 u67995.cpp

#include

typedef int Widget;

void myFunction(Widget w, int parameter);

int main()
{
myFunction(3, 3);
myFunction(1, 0);
myFunction(2, 1);
myFunction(3, 3);

printf ("Donen");
return 0;
}

void myFunction(Widget w, int parameter)
{
// some variables
static Widget buttons[2];
// more variables

switch (parameter)
{
case 0: buttons[0]=w; break;
case 1: buttons[1]=w; break;
case 3:
/* do stuff on buttons, will crash if not initialized */
printf (" button 1 value = %d , parameter = %dn", buttons[0], parameter);
printf (" button 2 value = %d , parameter = %dnn", buttons[1], parameter);

break;
}
}

$ icc -V
Intel C Intel 64 Compiler Professional for applications running on Intel 64, Version 11.1 Build 20090630 Package ID: l_cproc_p_11.1.046
Copyright (C) 1985-2009 Intel Corporation. All rights reserved.

$ icc -mia32 u67995.cpp
$ ./a.out
button 1 value = 0 , parameter = 3
button 2 value = 0 , parameter = 3

button 1 value = 1 , parameter = 3
button 2 value = 2 , parameter = 3

Done

Thank you very much for your answers, Tim and Om.
I will prepare a test case in the following week, when I return from a business trip.

I am still not able to make a test case out of my larger project (but I have tried).

Nevertheless I do have some more information about the behavior of this bug:
Program works correctly if compiled with gcc (-O1, -O2, -O3) or icc with -O0
but if I compile it with icc using -O1 or higher, it fails to initialise some static variables.

Even more puzzling, if I do a printf with value immediately after the initialisation within the
case xx:
set value to static variable;
print value of static variable;
break;
then the value is retained in the static variable, otherwise not.
It looks to me as if the actual assignement would be optimized out by code optimization by mistake, in some special cases. Or if the jump for the case would be incorrect.
I have also used ddd to set the breakpoint, and then watch the variable for modification.
Strangely, in the buggy run, it never reports that the varaible was changed.
Like I already said, Valgrind does not report any memory overwrites.
Any ideas of how to debug such cases?

You may try the binary search as given below to locate the source segment:

1. Create a directory for -O0 built objects and binaries of the project (say /good).
2. Create another directory for O1 built object and binaries of the project (say /bad).
3. Locate the faulty module using the binary search as given below:
a. Create a /temp directory and copy 50% modules from /good and remaining 50% from /bad.
b. Build the executable.
c. Run the executable
i. If failed then we know the faulty module is from /bad then replace another half of the /bad modules from /good to temp and go to step b.
ii. If passed then also we know the faulty module is in /bad that we did not copy. Copy another half of /bad modules to temp and go to step b.
4. Once the bad module is known, you can apply the above process for searching bad object file.
5. After knowing the bad object you can search the faulty function by above process. You may have to divide the code in two files for the above binary search.
6. Once the faulty function is known, you can disable optimization for this function by using #pragma optimize (, off/on).

Is this still an issue with latest Intel compiler? If so, please provide the test case.

 

Om

>>but if I compile it with icc using -O1 or higher, it fails to initialise some static variables.

Your source statement is not initializing the static variable.

you use: static Widget buttons[2];
not: static Widget buttons[2] = { 0, 0};

 Jim Dempsey

www.quickthreadprogramming.com

Thans, the issue was resolved with a compiler upgrade.

Widgets were initaliset during run-time, and set before they were used.

So the bug in compiler was real.

Leave a Comment

Please sign in to add a comment. Not a member? Join today