root@libove.UUCP (The Super User) (06/29/88)
A game was posted some time back called "puzzle". It doesn't work
under SCO Xenix development system 2.1.4g because if compiled with
small model, the single 64K segment isn't sufficient for all its
data, and if compiled under large model it core dumps along the lines
of the much simplified example that follows.
Can anyone explain this?
[root]/tmp:(1 ) % cat argle.c
#include <stdio.h>
#include <sgtty.h>
main()
{
char buffer[1024];
printf("%d\n",tgetent(buffer,getenv("TERM")));
};
[root]/tmp:(2 ) % cc -Ml2e -o argle argle.c -ltermcap
argle.c
[root]/tmp:(3 ) % ./argle
./argle: Segmentation violation -- Core dumped
[root]/tmp:(4 ) % adb argle core
* $c
tnamatch1d82efe8(5436., 0.) from tget1ent1d82efe8+320.
tget1ent1d82efe8(4280., 71., 5436., 0.) from _tgetent+29.
_tgetent(4280., 71., 5436.) from _main+38.
_main(1., 5338., 71., 5346., 71.) from __start+94.
__start() from start0+7.
*
[root]/tmp:(5 ) % cc -o argle argle.c -ltermcap
argle.c
[root]/tmp:(6 ) % ./argle
1
[root]/tmp:(7 ) %
This is an a PCs Limited AT (IBM PC/AT clone, 8 Mhz) with SCO Xenix 2.2.1
(modified with Ptydriver) and 2.1.4g development system.
Jay Libove Internet: libove@cs.cmu.edu libove@andrew.cmu.edu
5313 Ellsworth Avenue formtek!ditka!libove!libove@pt.cs.cmu.edu
Pittsburgh, PA 15232 UUCP: cmucspt!formtek!ditka!libove!libove
(412) 621-9649 cadre!pitt!darth!libove!libove
rosso@sco.COM (Ross Oliver) (07/02/88)
In article <54@libove.UUCP> Jay Libove illistrates the single most common mistake in large-model 286 programs. The example he gives, when compiled using "cc -M2l..." will dump core on execution: >#include <stdio.h> >#include <sgtty.h> > >main() > { > char buffer[1024]; > > printf("%d\n",tgetent(buffer,getenv("TERM"))); > }; Note that the return value of getenv() is not declared, therefore, the compiler assumes int. However, tgetent is expecting a char *, and in large-model 286 programs, int != char *. So, when main() calls tgetent, it passes only two of the four bytes returned by getenv(). tgetent picks up garbage data as the other two bytes, and (suprise!) a segmentation violation results. How can this be fixed? With the following declaration: char *getenv(); Here are a few tips to avoid problems like this in large-model 286 programs: - Declare your functions' return values. - Don't use "0" to mean NULL ( i.e. (char *)0 ). - Don't interchange ints and pointers, or longs and pointers. Ross Oliver SCO Technical Support
james@bigtex.uucp (James Van Artsdalen) (07/04/88)
IN article <701@nod2sco>, rosso@sco.COM (Ross Oliver) wrote: > Here are a few tips to avoid problems like this in large-model > 286 programs: > - Declare your functions' return values. > - Don't use "0" to mean NULL ( i.e. (char *)0 ). This last statement is incorrect, or rather, evidence of a broken compiler. C requires that the integer constant 0 be assignable to *any* pointer type. C also requires that any pointer type may be compared with the integer constant 0. If the Xenix compiler requires that the integer constant 0 be cast to a pointer type first, it is broken. -- James R. Van Artsdalen ...!ut-sally!utastro!bigtex!james "Live Free or Die" Home: 512-346-2444 Work: 328-0282; 110 Wild Basin Rd. Ste #230, Austin TX 78746
markz@ssc.UUCP (Mark Zenier) (07/05/88)
In article <3222@bigtex.uucp>, james@bigtex.uucp (James Van Artsdalen) writes: : IN article <701@nod2sco>, rosso@sco.COM (Ross Oliver) wrote: : > Here are a few tips to avoid problems like this in large-model : > 286 programs: : : > - Declare your functions' return values. : > - Don't use "0" to mean NULL ( i.e. (char *)0 ). : : This last statement is incorrect, or rather, evidence of a broken : compiler. > : C requires that the integer constant 0 be assignable to *any* pointer : type. C also requires that any pointer type may be compared with the : integer constant 0. If the Xenix compiler requires that the integer : constant 0 be cast to a pointer type first, it is broken. Until ANSI C exists, there is no way the compiler can tell type of the expression for a function arguement that is pushed on the stack. It would have been safer but much slower if Microsoft has chosen the default integer size at 32 bits for large model compiles. Mark Zenier uunet!pilchuck!ssc!markz "Kinda scary. One guy said he had heard they were a bunch of wierdo gourmets from somewhere in Orange County, looking for new taste thrills."
john@jetson.UUCP (John Owens) (07/05/88)
In article <3222@bigtex.uucp>, james@bigtex.uucp (James Van Artsdalen) writes: > > - Don't use "0" to mean NULL ( i.e. (char *)0 ). > C requires that the integer constant 0 be assignable to *any* pointer > type. C also requires that any pointer type may be compared with the > integer constant 0. If the Xenix compiler requires that the integer > constant 0 be cast to a pointer type first, it is broken. Correct, as far as it goes. 0 must be *assignable* to any pointer type, and the Xenix C compiler should extend it appropriately. Also, when using ANSI C function prototypes, 0 in an argument should be extented to the size of a pointer. But in non-ANSI C, in a large-data model, when passing a null pointer as an argument to a function expecting a pointer argument, "0" will not do, but "(pointer-type *)0" will. This indicates nothing wrong with the Xenix C compiler.] [For anyone who's still not convinced, make the analogy to floats (doubles, actually). While double f; f = 0; works, and double f; extern double fabs(); f = fabs((double)0); works, double f; extern double fabs(); f = fabs(0); /* expects a double */ will not.] -- John Owens SMART HOUSE Limited Partnership john@jetson.UUCP (old uucp) uunet!jetson!john +1 301 249 6000 (internet) john%jetson.uucp@uunet.uu.net
peter@ficc.UUCP (Peter da Silva) (07/07/88)
In article <3222@bigtex.uucp>, james@bigtex.uucp (James Van Artsdalen) writes: > IN article <701@nod2sco>, rosso@sco.COM (Ross Oliver) wrote: > > Here are a few tips to avoid problems like this in large-model > > 286 programs: > > - Don't use "0" to mean NULL ( i.e. (char *)0 ). > This last statement is incorrect, or rather, evidence of a broken > compiler. He's speaking in the context of a function call. Large model 286 programs have 32 bit pointers but 16 bit integers, so if you pass 0 to a function expecting a pointer the stack will be off by two bytes. So, the problem isn't a broken compiler, it's a broken CPU architecture. -- -- `-_-' Peter (have you hugged your wolf today) da Silva. -- U Ferranti International Controls Corporation. -- Phone: 713-274-5180. CI$: 70216,1076. ICBM: 29 37 N / 95 36 W. -- UUCP: {uunet,academ!uhnix1,bellcore!tness1}!sugar!ficc!peter.
tif@cpe.UUCP (07/08/88)
Written 1:42 pm Jul 6, 1988 by ficc.UUCP!peter in cpe:comp.sources.d
>So, the problem isn't a broken compiler, it's a broken CPU architecture.
The problem is broken programming practices. 1/2 :-)
Paul Chamberlain
Computer Product Engineering, Tandy Corp.
ihnp4!sys1!cpe!tif
allbery@ncoast.UUCP (Brandon S. Allbery) (07/09/88)
As quoted from <54@libove.UUCP> by root@libove.UUCP (The Super User): +--------------- | [root]/tmp:(1 ) % cat argle.c | #include <stdio.h> | #include <sgtty.h> | | main() | { | char buffer[1024]; | | printf("%d\n",tgetent(buffer,getenv("TERM"))); | }; | [root]/tmp:(2 ) % cc -Ml2e -o argle argle.c -ltermcap | argle.c | [root]/tmp:(3 ) % ./argle | ./argle: Segmentation violation -- Core dumped +--------------- If you use large model you have to include an "extern char *getenv();", or tgetent() will get a truncated pointer: C passes an undeclared function argument as an (int), which is 2 bytes, but a large-model (char *) is 4 bytes. This is an example of a gratuitous 680x0/Vax-ism, nonportable to systems where sizeof (int) != sizeof (char *). The core dump occurs when tnamatch() tries to access the string passed to it, and gets a pointer with a random value. -- Brandon S. Allbery, uunet!marque!ncoast!allbery DELPHI: ALLBERY For comp.sources.misc send mail to ncoast!sources-misc
allbery@ncoast.UUCP (Brandon S. Allbery) (07/12/88)
As quoted from <3222@bigtex.uucp> by james@bigtex.uucp (James Van Artsdalen): +--------------- | IN article <701@nod2sco>, rosso@sco.COM (Ross Oliver) wrote: | > Here are a few tips to avoid problems like this in large-model | > 286 programs: | | > - Declare your functions' return values. | > - Don't use "0" to mean NULL ( i.e. (char *)0 ). | | C requires that the integer constant 0 be assignable to *any* pointer | type. C also requires that any pointer type may be compared with the | integer constant 0. If the Xenix compiler requires that the integer | constant 0 be cast to a pointer type first, it is broken. +--------------- Only true in all cases IF (1) your compiler supports ANSI prototypes and (2) you use them. Otherwise, passing untyped 0 to a function expecting a pointer fails for the same reason that the getenv() in the original code did: the compiler can't figure out what type is needed there, so it uses (int). -- Brandon S. Allbery, uunet!marque!ncoast!allbery DELPHI: ALLBERY For comp.sources.misc send mail to ncoast!sources-misc