[net.lang.c] Funny bugs in some C compilers

padpowell@wateng.UUCP (PAD Powell[Admin]) (08/30/83)

I hit a really odd bug the other day, and just thought I would pass it along
to the C compiler community.  Suppose that I have a structure,
with fields of various widths, and my machine architecture demands that
I have addresses on various alingments.  For the sake of argument,
char is any alignment, short is mod 2 (2 chars), int is mod 4, and float is
mod 16.  The structure I defined was:
struct test {
	char c; short s; int i; float f; }
I pass a struct value to a subroutine (I mean function), and also have a local
variable.
test_funct( s ) struct test s;
	{ struct test t; /* bunch of assignments */ return( s == t) }
Now in the "bunch of assignments, I set the various fields of t to the same
values as the fields of s.  According to various persons, in the extended
version of C, passing a structure by "value" is permitted.  Also, comparison
and assignment of structures is permitted.  However,  this code fails with
several compilers, for the funny reason that the comparison fails.  When the
"t" variable is allocated on the stack, the "cracks" or unused space in the
structure are set to garbage.  The code usually generated for comparison will
compare the entire structure in the most effective manner, usually using a block
comparison instruction.  This is one of the most annoying of all types of
language "flakes",  which has been called by various people the "semantic
gap",  or the problems of mapping a language to a machine architecture.

I suppose that there is a way of fixing this.
1.  Extend the definition of the language so that all local variables are
	initialized to 0.
	Pro: it solves the problem.
	Con: THE OVERHEAD!!!!  Function calls are bad enough, and now you
	want to make them worse?
2.  Extend the definition so that all "cracks" in structures are set to 0.
	Pro: it solves the problem.
	Con: overhead is still substantial.  Reduces the cost, but is still
	pretty bad.
3.  Write a big BOLDFACED, BOXED, and perhaps dayglow orange warning in
	the language definition manual, and indicate that keeping around
	a static or global variable, set to all 0's, and assignment of it
	to a structure variable will guarantee that the "cracks" are
	filled with 0's.
	Pro: it probably will solve the problem.
	Con: Manuals are never read.  The problem still exists, and people
	will still hit it.  This will lead to net.lang.c getting flames about
	once every 6 months from the next group of people to hit this...
	Also, assignment of structure to structure must be defined so that
	the crack filling is guaranteed to work.

Patrick Powell, U. Waterloo, Waterloo, Ont.
...watmath!wateng!padpowell

ark@rabbit.UUCP (09/01/83)

wateng!padpowell complains that structure comparison doesn't do
the "right think" with the padding between elements.

Now you know why structure comparison isn't part of the language.
The only things you can do with a structure are:  take its address,
select an element of it, pass it to a function, return it as a value,
and assign it to another (identical) structure.

guy@rlgvax.UUCP (Guy Harris) (09/02/83)

According to "Recent Changes to C", distributed both with V7 and System III
UNIX:

	"Structures may be assigned, passed as arguments to functions, and
	returned by functions. ... Other plausible operators, such as
	equality comparison, have not been implemented."

From a document distributed in machine-readable form only(!) with System III:

	Structure assignment has been added to the C language
	to simplify both the source and object code associated
	with transferring the value of one structure instance to
	another and to allow functions to return aggregate
	values when invoked.
	Since many processors now contain some type
	of `move block' instruction, structure assignment
	will permit more efficient use of many machines.
	It also makes source programs more readable.

	Structures may be assigned, passed as arguments to functions,
	and returned by functions.
	The types of structure operands taking part must be the same.
	Other plausible operators, such as equality comparison
	and structure casts,
	are not being implemented due
	to the difficulties associated with "holes"
	in structures caused by alignment restrictions.

So the problem with structure comparison is known; in fact, that's why none
of the C compilers I've encountered implement it.

	Guy Harris
	{seismo,mcnc,we13,brl-bmd,allegra}!rlgvax!guy

alan@allegra.UUCP (09/02/83)

Gee, if every compiler writer and his uncle adds his favorite extension to
the language -- structure comparison, string manipulation, or whatever --
C can become as plauged by portability problems as Pascal is.  What fun!


	Alan Driscoll
	Bell Labs, Murray Hill

mrm@datagen.UUCP (09/02/83)

I was under the opinion that structure comparisions were forbidden
(as well as structure casts) because of just the problem you mention.

	Michael Meissner	Data General Corporation
	...(decvax!ittvax, allegra)!datagen!mrm

decot@cwruecmp.UUCP (Dave Decot) (09/14/83)

Seems to me that another solution to the "holes" problem of structure
comparison is somewhat clear:

	Permit comparison of two structures of the same tag or typedef
	for [in]equality only.  If the structure template involved contains
	no holes, compare the structures using a block-compare instruction
	(if available).  If there ARE holes, the result is the && conjunction
	[|| disjunction] of comparisons for [in]equality of constituent blocks
	that have no holes.
	
Thus, those areas of the structures that should be equal are compared,
and those that are "holes" are ignored, and the code thus generated can
be no worse than that generated by the poor programmer who has to
code this comparison by "hand".

No?  Replies are encouraged.

					Dave Decot
					..!decvax!cwruecmp!decot

dmmartindale@watcgl.UUCP (Dave Martindale) (09/14/83)

	From: decot@cwruecmp.UUCP (Dave Decot) Newsgroups: net.lang.c

	Seems to me that another solution to the "holes" problem of
	structure comparison is somewhat clear:

		Permit comparison of two structures of the same tag or
		typedef for [in]equality only.  If the structure
		template involved contains no holes, compare the
		structures using a block-compare instruction (if
		available).  If there ARE holes, the result is the &&
		conjunction [|| disjunction] of comparisons for
		[in]equality of constituent blocks that have no holes.

	Thus, those areas of the structures that should be equal are
	compared, and those that are "holes" are ignored, and the code
	thus generated can be no worse than that generated by the poor
	programmer who has to code this comparison by "hand".

This would prevent you from storing C-style strings in these structures.
Arrays which are used as arrays must, of course, have all elements
compared.  But the semantics of comparing a conventional C string call
for comparing bytes only until a null byte is reached; the contents
of the bytes in the char array following the null byte are often
garbage from a longer string which previously occupied that memory.

If someone were hand-coding the comparison of two structures, they
would use either strcmp (or strncmp) or a block compare of some sort
depending on their knowledge of whether each char array really contained
a string or not.  The compiler cannot know.

To have byte-by-byte comparison work properly, you must switch to
string-copying routines which always ensure that the destination is
padded with some well-defined pattern (probably nulls) to its end.

edler@cmcl2.UUCP (09/14/83)

#R:wateng:-27500:cmcl2:15400004:000:711
cmcl2!edler    Sep 14 16:54:00 1983

The following suggestion has been made:

	Permit comparison of two structures of the same tag or typedef
	for [in]equality only.  If the structure template involved contains
	no holes, compare the structures using a block-compare instruction
	(if available).  If there ARE holes, the result is the && conjunction
	[|| disjunction] of comparisons for [in]equality of constituent blocks
	that have no holes.
	
This won't work for structures containing unions of different-sized
components.  For example, I don't see how any C compiler can compare
two instances of the following structure:

	struct a {
		int b;
		union {
			char c;
			long d;
		} e;
	};

	Jan Edler	cmcl2!edler	(New York University)
			edler@nyu

ka@spanky.UUCP (Kenneth Almquist) (09/18/83)

Before we discuss how to implement structure comparison, we should
consider whether structure comparison should be implemented at
all.  I don't think it should.  I think that the number of programs
that could benefit from a structure comparison operator is quite
small.  (My opinion, anyone want to come up with a list of cases
where structure comparison would be useful?)  As a result, some
compiler implementers will probably not bother with structure
comparison and so that people will tend to avoid the feature to
ensure portability even if they do have a use for it.  In short,
I expect structure comparison to become known as a feature that
flopped if it is added to C.
						Kenneth Almquist