mikem@otc.OZ (Michael Mowbray) (12/19/86)
(I don't know whether this subject has already been posted, but a reminder
won't hurt anyway.)
In C++, if a class has a constructor taking a reference to itself, this
is used to advantage whenever instances of that class are passed to or
returned from functions. Essentially, an auxiliary pointer argument is passed
telling the function where the instance is, or where to compose the result,
respectively. This saves a bit-wise copy.
Unfortunately, I understand that a number of c-compilers have a bug that
causes a core dump if nothing is actually returned (when a struct was supposed
to be returned). The C++ translator handles that case by inserting dummy
code when necessary, depending on whether RETBUG was defined when cfront
was compiled. In the default distribution this is the case. So you may be
running a cfront that generates this dummy code (and hence introduces
run-time inefficiencies) even though you don't have to.
The following c program allows you to determine whether your c compiler
has the bug. Compile and run it. If it dumps core you have the bug. If
it doesn't, then you may wish to edit the cfront makefile to undefine
RETBUG, and then re-make cfront.
struct Crap {
int i;
};
struct Crap f(cp,ip)
struct Crap *cp;
int *ip;
{
cp->i = (*ip)++;
return;
}
main()
{
struct Crap c;
int i=0;
f(&c,&i);
printf("%d %d\n",c.i,i); /* should just print: 0 1 */
}
The Pyramid c compiler is fine. The Sun c compiler is NOT. (I wonder if this
is fixed in the SunOS release.)
I don't recall seeing anything about this in the C++ release notes. Maybe
there ought to be something.... (?)
Mike Mowbray
Systems Development
Overseas Telecommunications Commission (Australia)
UUCP: {seismo,mcvax}!otc.oz!mikem ACSnet: mikem@otc.ozsolomon@crys.WISC.EDU (Marvin Solomon) (12/21/86)
Mike Mowbray pointed out that cfront contains an option (turned on in the default version) to generate code to get around a C compiler bug, and supplies a test program to check whether your C compiler has that bug. His instructions are: > The following c program allows you to determine whether your c compiler > has the bug. Compile and run it. If it dumps core you have the bug. If > it doesn't, then you may wish to edit the cfront makefile to undefine > RETBUG, and then re-make cfront. Unfortunately, the bug may be present even if the program compiles and runs "correctly". The Berkeley 4.3 UNIX compiler for the VAX (as well as the 4.3beta and, I suspect, all earlier compliers) generates incorrect code, but the incorrect code is harmless. It copies a longword from location 0 to another location. On a SUN, virtual address 0 is not a legal address, but on a VAX (under Berkeley UNIX) it is. To make the program core dump, change the initialization of i from 0 to -1. Here is the modified test program: struct Crap { int i; }; struct Crap f(cp,ip) struct Crap *cp; int *ip; { cp->i = (*ip)++; return; } main() { struct Crap c; int i = -1; f(&c,&i); printf("%d %d\n",c.i,i); /* should just print: 0 1 */ } And here is the assembler language generated by 'cc -S' (with annotation): LL0: .data .text .align 1 .globl _f _f: .word L12 jbr L14 L15: movl *8(ap),r0 / r0 = *ip incl *8(ap) / ip++ movl r0,*4(ap) / cp->i = *ip jbr L13 L13: .lcomm L16,4 / return: movab L16,r1 / r1 = &temp movl (r0),(r1) / *r1 = *r0 (!) movab L16,r0 / return &temp ret .set L12,0x0 L14: jbr L15 .data .text .align 1 .globl _main _main: .word L18 jbr L20 L21: mnegl $1,-8(fp) subl3 $8,fp,r0 pushl r0 subl3 $4,fp,r0 pushl r0 calls $2,_f .data 1 L23: .ascii "%d %d\12\0" .text pushl -8(fp) pushl -4(fp) pushl $L23 calls $3,_printf ret .set L18,0x0 L20: subl2 $8,sp jbr L21 .data -- Marvin Solomon Computer Sciences Department University of Wisconsin, Madison WI solomon@gjetost.wisc.edu or seismo!uwvax!solomon
chris@mimsy.UUCP (Chris Torek) (12/22/86)
In article <213@crys.WISC.EDU> solomon@crys.WISC.EDU (Marvin Solomon) writes: >... cfront contains an option (turned on in the default version) >to generate code to get around a C compiler bug. ... >Unfortunately, the bug may be present even if [a previously posted >test] program compiles and runs "correctly". The Berkeley 4.3 UNIX >compiler for the VAX (as well as the 4.3beta and, I suspect, all >earlier compliers) generates incorrect code, but the incorrect >code is harmless. Sometimes! It depends on whatever happens to be in r0. E.g., struct foo { int f; }; struct foo f() { g(); return; } int g() { return (0xc0000000); } main() { f(); exit(0); } will crash. >Here is the modified test program: > struct Crap { int i; }; > struct Crap f(cp,ip) > struct Crap *cp; > int *ip; > { > cp->i = (*ip)++; > return; > } This program does indeed point out a bug in the 4.3BSD compiler (and in lint, which does not complain), but the code itself is wrong as well. The function is declared to return an object of type `struct Crap'; all the paths out of this function must return such an object. For example, return (*cp); would be correct. `return;' is not, nor is falling off the end of the function without a `return'. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690) UUCP: seismo!mimsy!chris ARPA/CSNet: chris@mimsy.umd.edu