Date: Thu, 26 Jun 1997 14:27:17 -0700 (PDT) Message-Id: <199706262127.OAA25663@adit.ap.net> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" To: djgpp AT delorie DOT com From: Nate Eldredge Subject: Bug (?) in GCC - discarded struct returns Precedence: bulk I've found a problem with GCC that I don't know whether to describe as a bug or just compiler stupidity. The problem is that when calling a function returning a struct several times and ignoring the return value, space is allocated on the stack for *each* of the ignored structs. (Confusing, I know.) Perhaps my (long) example will help explain: -- cut -- #include /* A large struct type */ struct big_struct { char string_member[1000]; int more_data; } ; /* A function returning a big_struct */ struct big_struct do_something(void) { struct big_struct local_struct; /* ... Imagine this function doing * * something of interest here ... */ /* Now fill local_struct with some stuff */ strcpy(local_struct.string_member,"hi there"); local_struct.more_data = 12345; /* And return it */ return local_struct; } int main(void) { /* Although no local variables, main requires stack space * * of sizeof(struct big_struct) * (number of calls to do_something) */ /* Suppose we want to do_something a lot */ do_something(); do_something(); do_something(); do_something(); do_something(); do_something(); return 0; } --cut-- If you compile this and look at the resulting assembly, you will notice that main allocates about 6000 bytes on the stack. The returned struct from each call to do_something is placed in a slot of its own, as if it were a local variable. Since it's never used again, this is a big waste of 5K. If big_struct were much larger, or there were more calls to do_something, you might overflow your stack, causing bafflement ("I don't use big auto arrays or anything!"). I realize part of this is a side effect of Gnu CC's clever struct-returning scheme (the address of where it will go is passed as an invisible parameter). *Some* address has to be passed, with space to hold the data, so stack space is allocated. One would hope, however, that the compiler would be smart enough to have them all dump their ignored structs into the same stack slot. To work around, you could explicitly assign the results to a variable and then not use it: --cut-- int main(void) { struct big_struct garbage_can; /* :) */ garbage_can = do_something(); garbage_can = do_something(); /* etc... */ return 0; } --cut-- Turning on optimizations has no effect on this problem (except that -O3 or -finline-functions make it a lot harder to see). Unless someone can think of a justification for this inefficiency, I'm going to report it to GNU. Nate Eldredge eldredge AT ap DOT net