c/4101: gcc 2.95.4 compiles bad code with nested static functions

chitty@libero.it chitty@libero.it
Thu Aug 23 11:26:00 GMT 2001


>Number:         4101
>Category:       c
>Synopsis:       gcc 2.95.4 compiles bad code with nested static functions
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          wrong-code
>Submitter-Id:   net
>Arrival-Date:   Thu Aug 23 11:26:00 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     Cristiano Milia
>Release:        gcc version 2.95.4 20010319 (Debian prerelease)
>Organization:
>Environment:
Linux 2.4.6-mosix #1 SMP i686 
>Description:
f2 is a function defined into another function body, and f pointer is declared static in the same scope of f2.

when assigning address of f2 to f, the correct assignment is correctly done ONLY IF the BODY of f2 is defined AFTER the assignment statement.

the result of this wrong address generation is an "illegal instruction" at runtime, when executing (*f)().

the fact is that f is assigned a value that is NOT the actual f2 value.
it seems to me that if f2 is DEFINED before the assignment statement, gcc gets confused about its address, that is not the one f2 had when it was DECLARED. 

function_2 can be have an empty body or not, it always happens.
>How-To-Repeat:
/* this must do a certain thing only the 1st time,
   but we don't want a check as if (first_time) {do},
   so we use a function pointer that the first time
   does, the others just returns.
 */
void loop(void) 
{
   void f1(void);
   void f2(void);
   static void (*f)(void) = f1;

   void f2(void) { } /* this is empty */

   void f1(void)
   {
      /* ... do something */
      f=f2; /* the problem is HERE */
   }

   (*f)(); /* do something only the first time */
}

int main()
{
   loop();
   loop(); /* second time it crashes! */
}
>Fix:
just put the DEFINITION of f2 AFTER the assignment statement:

void loop(void)
{
   void f1(void);
   void f2(void);

   static void (*f)(void) = f1;

   void f1(void)
   {
      f=f2; /* NOW it correctly assigns the address of f2 */
   }

   void f2(void) { }

   (*f)();
}
>Release-Note:
>Audit-Trail:
>Unformatted:



More information about the Gcc-bugs mailing list