Optimization considered harmful

Brad Sherman bks at alfa.berkeley.edu
Wed Oct 31 12:41:32 AEST 1990


I have included a program below which is broken by the Microsoft 6.0
compiler on MSDOS.   While this is no great surprise, the circumstances
that break the code have caused some concern in our shop.

The compiler only generates bad code under certain conditions (outlined
below) but the gist is this:  the interaction between the use of the
keyword "register" and the attempts of the compiler to perform
some optimization causes faulty assembly language to be generated.
We guess that this is because the compiler "runs out of registers."
(Is that excessively anthropomorphic?)

We port code to many different platforms (MSDOS, NOVELL, UNIX, VMS, ... )
and attempt to write maximally portable C.  Normally we test and
debug our code and *then* use the optimizer.

Now, which of the following lessons should be drawn from this event:
	1) Don't use "register."
	2) Don't use optimizers (or in this case be sure to disable optimizer).
	3) Don't use "improved" Microsoft products.
Unfortunately, not porting to MSDOS is precluded

-- Brad Sherman (bks at alfa.berkeley.edu)


-------Program listing follows----------------------------------

/*
 *	Program breaks under MSC 6.0.
 *	Compile cl /AL /o prog prog.c.  The program will break
 *	at checkpoint 3, and MSDOS will hang shortly thereafter.
 *	Will compile and run correctly if:
 *		Compiled with MSC 5.1.
 *		Compiled small or medium memory model.
 *		Compiled with no optimization /Od.
 *		Compiled with all optimizations /Ox.
 *		Keyword "register" is removed!
 *	You can look at the assembly language listing and see that
 *	an address stored in a register is getting clobbered.  The
 *	problem is not due to lack of memory.  Substituting pointer
 *	arithmetic [(*(s_array +i))->s] for array notation has no
 *	salutory affect.
 */
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

typedef struct string {
	char *s;
	int  len;
} STRING;

main()
{
	register int i;
	STRING **s_array;
	if ((s_array = (STRING **)malloc(100 * sizeof(STRING))) == NULL) {
		printf("Problem at 1\n");
		exit(1);
	}
	for (i = 0; i < 100; i++) {
		if ((s_array[i] = (STRING *)malloc(sizeof(STRING))) == NULL) {
			printf("Problem at 2 with i=%d\n", i);
			exit(1);
		}
		if ((s_array[i]->s = (char *)malloc(10)) == NULL) {
			printf("Problem at 3 with i=%d\n", i);
			exit(1);
		}
	}
}



More information about the Comp.lang.c mailing list