PCC, lint bug

BostonU SysMgr root%bostonu.csnet at csnet-relay.arpa
Mon Sep 2 06:23:51 AEST 1985


>This really belonged in net.lang.c, for reasons which will be apparent
>shortly...
>
>> The following totally reasonable looking garbage compiles and passes
>> lint -hp without a peep. It printed garbage on my 4.2 VAX, core dumped
>> on my UNIX/PC (SYSV). I realize the difference between a two dimensional
>> array and a pointer to a pointer (or whatever, pluralize), apparently
>> neither C nor lint does. Sorry if this has been covered.
> (excerpted)
> ----------
>> 	int x[2][2] ;
>> 	int **xp = x ;
>> 			printf("%d\n",x[i][j] = i+j) ;
>> 			printf("%d\n",xp[i][j]) ;
>
>C does know the difference between "array of X" and "pointer to X"; however,
>when the name of an "array of X" is used it evaluates to a pointer to the
>first member of that array, hence a "pointer to X".
>
>xp[i][j] is (xp[i])[j].  xp[i] is *(xp + i).  "xp" is a pointer to a pointer
>to an "int", as is xp + i.  *(xp + i) is thus a pointer to an "int".
>(xp[i])[j] is thus (*(xp + i))[j].  Call *(xp + i) Xp.  (xp[i])[j] is Xp[j].
>This is *(Xp + j).  "Xp" is a pointer to an int, as is Xp + j, so *(Xp + j)
>is an "int".  The code is perfectly legal C.  Any C compiler or "lint" which
>*rejected* it would have a bug.  Why the program drops core is left as an
>exercise for the reader.  (Hint - has what "xp" points to been initialized?
>Is code that dereferences an uninitialized pointer likely to work?)
>
>	Guy Harris

WRONG WRONG WRONG

THE  ERROR IS ALLOWING THE DECLARATION TO PASS BOTH C AND LINT:

	int x[STUFF][THING] ;	/* the name 'x' is a pointer to an int */
	int **xp = x ;		/* not a pointer to a pointer */

I do not believe *any* reading of 'x' lets it be a pointer to a pointer.
My, ahem, point stands, it's a bug in the compiler not a misunderstanding
of C. The semantics of a two dimensional array (x[STUFF][THING]) is not
at all the same as an array of pointers (*x[STUFF]), the former involves
only a base pointer and STUFF*THING ints (in this case.) Therefore, perhaps,
UNIX-WIZARDS, not net.lang.c if I read intentions right (this is where
interesting global bugs go.)

Here is the code for a trivial proof of this on a VAX (4.2):

int x[4][3] ;	/* make these externs so the names show up in the asm */
int **xp = x ;	/* wrong, type clash,  but C nor LINT care */
int i ;
foo()
{
	i = 4 ;
	x[2][2] = i ;
	xp[2][2] = i ;
}
(Now, cc -S:)
LL0:
	.data
	.comm	_x,48		<- 4*3*sizeof(int)
	.align	2
	.globl	_xp
_xp:
	.long	_x		<- wrong, type clash
	.comm	_i,4
	.text
	.align	1
	.globl	_foo
_foo:
	.word	L15
	jbr 	L17
L18:
	movl	$4,_i
	movl	_i,_x+32	<- doesn't deref anything, correct (x[2][2])
	movl	_xp,r0		<- merrily derefs a pointer (xp[2][2])
				this is correct code, but the decl should
				have caused warnings
	movl	8(r0),r0
	movl	_i,8(r0)
	ret
	.set	L15,0x0
L17:
	jbr 	L18
	.data

If you are still not convinced this is a bug, change all the occurrances
of 'int' to 'char' above and run it through C and lint, lint only warns
when -hp (possible pointer alignment problem ?!?! still wrong.)

		-Barry Shein, Boston University



More information about the Comp.unix.wizards mailing list