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