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."
chip@vector.UUCP (Chip Rosenthal) (07/05/88)
{{{ The original article was in comp.sources.d too. }}} In article <3222@bigtex.uucp> you write: }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. XENIX does the right thing. You can do (char *) assignments and comparisons with zero. I still agree with the statement as a matter of style, but that's a diatribe better left for comp.lang.c :-(. -- Chip Rosenthal /// chip@vector.UUCP /// Dallas Semiconductor /// 214-450-0400 {uunet!warble,sun!texsun!rpp386,killer}!vector!chip I won't sing for politicians. Ain't singing for Spuds. This note's for you.
james@bigtex.uucp (James Van Artsdalen) (07/05/88)
IN article <414@vector.UUCP>, chip@vector.UUCP (Chip Rosenthal) wrote: > In article <3222@bigtex.uucp> james@bigtex.uucp wrote: > }IN article <701@nod2sco>, rosso@sco.COM (Ross Oliver) wrote: > }> - Declare your functions' return values. > }This last statement is incorrect, or rather, evidence of a broken > }compiler. > XENIX does the right thing. You can do (char *) assignments and > comparisons with zero. int *i, **p; i = 0; if (i != 0) printf("Broken compiler\n"); p = &i /* ie, not 0 */ if (p == 0) printf("Broken compiler\n"); Nobody is saying that "*i = 0; p = *i" needs to yield "p == 0". But the above tests should never fail or generate a warning under any memory model. I mean, if a compiler can handle long l; l = 0; surely it can handle the "integer constant 0" business (and if it doesn't handle either, you don't want it). I can't remember if uPort did this right with their 286 unix, but I expect better of SCO. -- 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
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
karl@ddsw1.UUCP (Karl Denninger) (07/06/88)
In article <3291@bigtex.uucp> james@bigtex.UUCP (James Van Artsdalen) writes:
#IN article <414@vector.UUCP>, chip@vector.UUCP (Chip Rosenthal) wrote:
#> In article <3222@bigtex.uucp> james@bigtex.uucp wrote:
#> }IN article <701@nod2sco>, rosso@sco.COM (Ross Oliver) wrote:
#> }> - Declare your functions' return values.
#
#> }This last statement is incorrect, or rather, evidence of a broken
#> }compiler.
#
#> XENIX does the right thing. You can do (char *) assignments and
#> comparisons with zero.
#
#int *i, **p;
#
#i = 0;
#if (i != 0)
# printf("Broken compiler\n");
#
#p = &i /* ie, not 0 */
#if (p == 0)
# printf("Broken compiler\n");
#
#Nobody is saying that "*i = 0; p = *i" needs to yield "p == 0". But
#the above tests should never fail or generate a warning under any
#memory model. I mean, if a compiler can handle
Under Xenix V/386 (2.2.1, 2.2.1 development set), it does not generate a
warning on compile, nor do I get any "Broken Compiler" messages when
executing the output...
The example given compiles and runs properly under small model '386, as
well as Small and large Model '286 code (I checked all three).
Please... check these assumptions! Xenix may have had these problems once
upon a time. All that's left seem to be the "infinite spill" errors
(grrr... you guys NEED to fix this one; it's the only really horrid
irritant I have found in an otherwise excellent development system).
--
Karl Denninger (ddsw1!karl) Data: (312) 566-8912, Voice: (312) 566-8910
Macro Computer Solutions, Inc. "Quality solutions at a fair price"
mike@cimcor.UUCP (Michael Grenier) (07/06/88)
: int *i, **p; : : i = 0; : if (i != 0) : printf("Broken compiler\n"); : : p = &i /* ie, not 0 */ : if (p == 0) : printf("Broken compiler\n"); : : surely it can handle the "integer constant 0" business (and if it : doesn't handle either, you don't want it). I can't remember if uPort : did this right with their 286 unix, but I expect better of SCO. uPort has no problem with this. -Mike Grenier mike@cimcor.mn.org
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.
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
donegan@stanton.TCC.COM (Steven P. Donegan) (07/10/88)
In article <517@cimcor.UUCP>, mike@cimcor.UUCP (Michael Grenier) writes: > : int *i, **p; > : > : i = 0; > : if (i != 0) > : printf("Broken compiler\n"); > : > : p = &i /* ie, not 0 */ ^ syntax error - needs ';' > : if (p == 0) > : printf("Broken compiler\n"); > : > : surely it can handle the "integer constant 0" business (and if it > : doesn't handle either, you don't want it). I can't remember if uPort > : did this right with their 286 unix, but I expect better of SCO. > > > uPort has no problem with this. > > -Mike Grenier > mike@cimcor.mn.org With the exception of the syntax error above, SCO 2.2.1 handled this program fragment properly on my system. What exactly are you all trying to say about the compiler being broken? What version of SCO's development system was under discussion - my news feed has been down for about 8-10 days and I'm not at all sure what point is trying to be made here. Thanks for any feedback...
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