ron@vsedev.VSE.COM (Ron Flax) (10/29/86)
Has anyone else out there been experiencing problems with porting programs to Microport Unix V/AT that fall into the large model category? It seems that most everything I port (try to port?) has pointer alignment problems, as indicated by lint, or just core dumps with a segmentation violation at strange places in the code, like on a strlen() call? Sdb seems to indicate a memory fault as the culprit and I think that most of the problems are pointer related since an 'int' ain't necessarily an 'int' (ie. 16 bits in small model, 32 bits in large model). Does anyone have any words of wisdom as to how one might go about fixing pointer alignment problems without too much pain? One other unrelated problem I have with Microport Unix is that for one reason or another the system seems to run for a while then when it decides its had enough it just plain goes south. It appears to be a deadlock situation since terminals that had active sessions going continue to echo keystroke even though it doesn't respond to them and non-active sessions (ie. getty's running) do NOT echo keystrokes. This obviously quite annoying as you might imagine... One other thing that is interesting is that I know of two other sites with the exact same problem on different hardware, but Microport claims they have never heard of it? Has anyone else seen this behavior? Incidentally I was running SCO Xenix V successfully for about 6 months prior to getting Microport Unix. Microport are you listening 8-) -- ron@vsedev.VSE.COM (Ron Flax) UUCP: ..!seismo!vsedev!ron ARPA: vsedev.VSE.COM!ron@seismo.CSS.GOV
campbell@maynard.UUCP (Larry Campbell) (10/31/86)
In article <188@vsedev.VSE.COM> ron@vsedev.VSE.COM (Ron Flax) writes: >Has anyone else out there been experiencing problems with porting >programs to Microport Unix V/AT that fall into the large model category? >It seems that most everything I port (try to port?) has pointer >alignment problems, as indicated by lint, or just core dumps with a >segmentation violation at strange places in the code, like on a strlen() >call? > >Sdb seems to indicate a memory fault as the culprit and I think that >most of the problems are pointer related since an 'int' ain't >necessarily an 'int' (ie. 16 bits in small model, 32 bits in large >model). Does anyone have any words of wisdom as to how one might go >about fixing pointer alignment problems without too much pain? The simplest solution is to get your code to pass through lint without complaints. The most common problem I've found (especially from code written on 68Ks and VAXen) is for people to not bother declaring pointer valued objects: char *p; p = malloc(128); oops, malloc is implicitly declared (int), not (char *), so you get a bogus pointer because ints are 16 bits while pointers are 32 bits. There should have been an "extern char *malloc();" in there. Lint will find these for you. -- Larry Campbell MCI: LCAMPBELL The Boston Software Works, Inc. UUCP: {alliant,wjh12}!maynard!campbell 120 Fulton Street, Boston MA 02109 ARPA: campbell%maynard.uucp@harvisr.harvard.edu (617) 367-6846
dan@prairie.UUCP (Daniel M. Frank) (10/31/86)
In article <188@vsedev.VSE.COM> ron@vsedev.VSE.COM (Ron Flax) writes: >Has anyone else out there been experiencing problems with porting >programs to Microport Unix V/AT that fall into the large model category? >It seems that most everything I port (try to port?) has pointer >alignment problems, as indicated by lint, or just core dumps with a >segmentation violation at strange places in the code, like on a strlen() >call? The problems aren't generally with Microport, they are with brain- damaged, unlinted programs that presume that sizeof int = sizeof *, or even (in one case), that ALL scalar data types are always the same size when passed into a function. Let me make a few observations and suggestions of how to find these problems and what to watch for. First, the lint you have is probably broken, unless you have the very latest release (in the last two days). You will find the new, repaired version of lint (and sdb, actually), very useful. Suggestion: compile everything with -g. sdb is very useful for finding obscure portability bugs that lint will not find (usually because of a VARARGS directive). Nasties to watch for: 1) Failure to declare functions returning long or *. The compiler will happily truncate return values to one word, which will usually cause segmentation violations very quickly, or in the case of long returns, cause odd program behaviour. malloc() and time() are favorites, as are string functions returning pointers. 2) Constructs of the form 1 << n, where n is greater than 15. Guess what happens? The compiler optimizes this to zeroing out a register. You want 1L << n. This bug is from compress.c 3) Silly function arguments, usually constants. time(0) is a popular one. This should be time((long *)0). 4) Very silly constant function arguments in varargs functions, where lint can't find them. execl and execle are very popular in this category. Watch for varargs functions that use null pointers to terminate lists; folks usually use 0 rather than the proper (char *)0. 5) Varargs functions that use a bunch of integer arguments to copy the stack. These are all over the place, in such classics as patch and inews. The method is not bad, per se, but usually there aren't enough of these arguments if ints are shorter than pointers. Redeclare them to be long instead. (I am posting this generally, rather than mailing back to the poster, because I would beg, implore, plead, and otherwise abase myself before authors of C programs posted to the net to try and be sensitive to some of these problems. Yes, I know the 286 is brain-damaged and all that, but a bunch of us got `em cheap from this guy in a plaid sport coat who told us that they were the wave of the future, and now we can't afford Suns. Watch for assumptions about pointer sizes. Use the varargs functions and macros provided in System V and BSD instead of bogus argument lists.) On the crash problem, try again with Microport support. Stress that there are not many multi-terminal sites, and that this is occurring on different hardware. Ask for Henry and use my name. Good luck! Dan -- Dan Frank uucp: ... uwvax!prairie!dan arpa: dan%caseus@spool.wisc.edu
campbell@maynard.UUCP (Larry Campbell) (11/01/86)
In article <271@prairie.UUCP> dan@prairie.UUCP (Daniel M. Frank) writes: >...On the crash problem, try again with Microport support. Stress >that there are not many multi-terminal sites, and that this is occurring >on different hardware. Ask for Henry and use my name. Poor Henry... he seems to be awfully busy these days. - A more-or-less satisifed Microport customer (well, so far the hassles I've encountered haven't negated the $800 I saved by going Microport instead of Xenix) who has had the opportunity to chat with Henry on several occasions... -- Larry Campbell MCI: LCAMPBELL The Boston Software Works, Inc. UUCP: {alliant,wjh12}!maynard!campbell 120 Fulton Street, Boston MA 02109 ARPA: campbell%maynard.uucp@harvisr.harvard.edu (617) 367-6846
dan@prairie.UUCP (Daniel M. Frank) (11/01/86)
In article <402@maynard.UUCP> campbell@maynard.UUCP (Larry Campbell) writes: >Poor Henry... he seems to be awfully busy these days. Actually, they just hired a roomfull of customer support people to help him out. He's still busy, though ... -- Dan Frank uucp: ... uwvax!prairie!dan arpa: dan%caseus@spool.wisc.edu
barber@rabbit1.UUCP (Steve Barber) (11/01/86)
In article <401@maynard.UUCP>, campbell@maynard.UUCP (Larry Campbell) writes: > In article <188@vsedev.VSE.COM> ron@vsedev.VSE.COM (Ron Flax) writes: > >Has anyone else out there been experiencing problems with porting > >programs to Microport Unix V/AT that fall into the large model category? > .... The most common problem I've found (especially from code > written on 68Ks and VAXen) is for people to not bother declaring pointer > valued objects: Another common problem is passing NULL as pointer argument. NULL is #defined as 0, which is 2 bytes. Large model pointers are 4 bytes, so the stack frame is now basically garbage. The solution is to cast the NULLs to the appropriate types. Ahhh..Intel..you can never be forgiven for making us have to worry about memory models (flames by mail only, please). -- Steve Barber Rabbit Software Corp. ...!ihnp4!{cbmvax,cuuxb}!hutch!barber ...!psuvax1!burdvax!hutch!barber (215) 647-0440 7 Great Valley Parkway East Malvern PA 19355
guy@sun.uucp (Guy Harris) (11/03/86)
> Another common problem is passing NULL as pointer argument. NULL is > #defined as 0, which is 2 bytes. Large model pointers are 4 bytes, so > the stack frame is now basically garbage. The solution is to cast the > NULLs to the appropriate types. Ahhh..Intel..you can never be forgiven > for making us have to worry about memory models... Yes, having to worry about memory models may be a pain; however, even if you didn't have multiple memory models, you'd *still* have to worry about properly declaring pointer-valued functions and casting null pointers. A 68K implementation might have 16-bit "int"s and 32-bit pointers, or might return the value of an integral-type-valued function in D0 and the value of a pointer-valued function in A0. Other implementations might not use an all-zero bit pattern to represent a null pointer. I really hope that when the ANSI C standard comes out, compilers start issuing warnings if you use a function that you haven't already declared, or if you don't declare the types of the arguments to a function. Yes, this may inconvenience programmers, but the ones it most inconveniences are the ones who just don't *care* about data types, and they're the ones who need the biggest attitude adjustment. -- Guy Harris {ihnp4, decvax, seismo, decwrl, ...}!sun!guy guy@sun.com (or guy@sun.arpa)
dan@prairie.UUCP (Daniel M. Frank) (11/03/86)
In article <245@rabbit1.UUCP> barber@rabbit1.UUCP (Steve Barber) writes: >Another common problem is passing NULL as pointer argument. NULL is >#defined as 0, which is 2 bytes. Large model pointers are 4 bytes, so >the stack frame is now basically garbage. This isn't really true. Code in stdio.h for the SV/286 release checks your memory model, and if it is large, defines NULL to be 0L, which is the same size as a pointer. It doesn't please lint, so the best solution is still to cast it as appropriate (like (char *)0), but you ARE generally safe, as long as you include stdio.h. -- Dan Frank uucp: ... uwvax!prairie!dan arpa: dan%caseus@spool.wisc.edu
campbell@maynard.UUCP (Larry Campbell) (11/04/86)
In article <347@prairie.UUCP> dan@prairie.UUCP (Daniel M. Frank) writes: >In article <245@rabbit1.UUCP> barber@rabbit1.UUCP (Steve Barber) writes: >>Another common problem is passing NULL as pointer argument. NULL is >>#defined as 0, which is 2 bytes. Large model pointers are 4 bytes, so >>the stack frame is now basically garbage. > > This isn't really true. Code in stdio.h for the SV/286 release >checks your memory model, and if it is large, defines NULL to be 0L, >which is the same size as a pointer. It doesn't please lint, so the >best solution is still to cast it as appropriate (like (char *)0), >but you ARE generally safe, as long as you include stdio.h. I wonder why stdio.h doesn't just declare NULL as "(char *) 0", or, in the brave new world of ANSI X-whatever, "(void *) 0"? This should do all the right things. -- Larry Campbell MCI: LCAMPBELL The Boston Software Works, Inc. UUCP: {alliant,wjh12}!maynard!campbell 120 Fulton Street, Boston MA 02109 ARPA: campbell%maynard.uucp@harvisr.harvard.edu (617) 367-6846
garry@batcomputer.TN.CORNELL.EDU (Garry Wiegand) (11/04/86)
In a recent article campbell@maynard.UUCP (Larry Campbell) wrote: >I wonder why stdio.h doesn't just declare NULL as "(char *) 0", or, >in the brave new world of ANSI X-whatever, "(void *) 0"? This should >do all the right things. To get *all* the right things, we use: #ifdef lint # define null 0 #else # define null (char *)0 #endif since lint doesn't understand that comparing an (int *) variable with a (char *)0 is legitimate. garry wiegand (garry%cadif-oak@cu-arpa.cs.cornell.edu)
gwyn@brl-smoke.ARPA (Doug Gwyn ) (11/04/86)
In article <405@maynard.UUCP> campbell@maynard.UUCP (Larry Campbell) writes: >I wonder why stdio.h doesn't just declare NULL as "(char *) 0", or, >in the brave new world of ANSI X-whatever, "(void *) 0"? This should >do all the right things. How quickly people forget. In pre-X3J11 C, no single data type is correct for null pointers in all contexts, particularly in actual parameters to functions. These should ALWAYS be written as NULL (or 0) cast to pointers of the correct type. The best definition of NULL in <stdio.h> for these implementations is the integer constant 0. Some of us would even argue that that is the only completely correct choice. In X3J11 C, if a function prototype is in scope, casting of function parameters is automatically done, and either (void *)0 or 0 is a correct definition for NULL. I recommend that you assume that NULL is defined to be the int constant 0 (even if it isn't on your current system), and always cast it to the correct pointer type when used as an actual parameter. This practice will continue to work under X3J11.
dave@ur-valhalla.UUCP (Dave Carlson) (11/05/86)
A potential problem I smacked into yesterday when porting BSD to SV/AT is ioctl(2) expects as the third argument: union { int iarg; char *cparg;} Problem is that the union will pull 4 bytes off the stack (in large model) but the program calling with an integer will only push 2 bytes. Oh S*$&! I cast my integer args long and everything seems ok but what a pain... I'm always a bit wary when I have to watch even system calls. Raver dave
guy@sun.uucp (Guy Harris) (11/05/86)
> I wonder why stdio.h doesn't just declare NULL as "(char *) 0", or, > in the brave new world of ANSI X-whatever, "(void *) 0"? This should > do all the right things. No, it shouldn't. Passing a "(char *)0" to a routine that expects an "int *" of some sort is NOT guaranteed to work. If, in fact, you have a machine on which "char *" is longer than "int *", it is very unlikely to work. In the brave new world of ANSI X3J11, the right thing to do is to use function prototypes; if you do this, almost all the 0's will be automatically converted into null pointers of the appropriate type by the compiler. (It still won't work for "execl"; if you hack NULL to be "(char *)0", it fixes *this* case, but it may not work for some routine that expects an "(int *)0" at the end of its argument list.) -- Guy Harris {ihnp4, decvax, seismo, decwrl, ...}!sun!guy guy@sun.com (or guy@sun.arpa)
guy@sun.uucp (Guy Harris) (11/05/86)
> To get *all* the right things, we use: > > #ifdef lint > # define null 0 > #else > # define null (char *)0 > #endif > > since lint doesn't understand that comparing an (int *) variable with a > (char *)0 is legitimate. If you use that particular construct, you will get a lot of perfectly legitimate "lint" complaints about argument mismatches when you pass a "null" to a routine that expects a pointer of some sort. Since, given the rationale for this construct, you presumably want to keep "lint" as quiet as possible, you presumably then cast "null" to the appropriate type. Given that, what does the non-"lint" arm of the conditional buy you, other than fixing up a few calls to things like "execl", which are easy enough to fix manually with casts? -- Guy Harris {ihnp4, decvax, seismo, decwrl, ...}!sun!guy guy@sun.com (or guy@sun.arpa)
wmam@sphinx.UChicago.UUCP (tony mason) (11/06/86)
In article <188@vsedev.VSE.COM> ron@vsedev.VSE.COM (Ron Flax) writes: >One other unrelated problem I have with Microport Unix is that for one >reason or another the system seems to run for a while then when it >decides its had enough it just plain goes south. It appears to be a >deadlock situation since terminals that had active sessions going >continue to echo keystroke even though it doesn't respond to them and >non-active sessions (ie. getty's running) do NOT echo keystrokes. This >obviously quite annoying as you might imagine... One other thing that >is interesting is that I know of two other sites with the exact same >problem on different hardware, but Microport claims they have never >heard of it? Has anyone else seen this behavior? Incidentally I was >running SCO Xenix V successfully for about 6 months prior to getting >Microport Unix. Microport are you listening 8-) > While running with SCO Xenix V all spring, we found that it would periodically do EXACTLY what you are describing. It made no difference what machine we used (IBM AT, SPERRY IT, even ALTOS 2086) it would die. After much in-depth research, and discussion with SCO's technical support (overworked, harried people it often took a week just to get to talk to) it turns out that it isn't too hard to get this problem to occur - just write a large model program on the 80286 that uses sbrk() (and is returning large pointers) and doesn't de-allocate at the end of the program (after all, why do that? The system takes care of it right?) this will lead to death. Symptoms are: 1. Terminals still echo characters 2. Disk activity periodically (sync?) 3. NOTHING can be done (except a reset) to get it back. This is the infamous LARGE MODEL DEATH. I was told by SCO that they had no fix for it, and that their technical engineers were stumped (something like, five of the last five "fixes" in house had failed to work.) Naturally, we tested this out on other machines, and yes, it occurs on them all. (This was disasterous because the product was using INFORMIX - which did have some large model pieces). Perhaps this is what you are experiencing (if not, it is an AMAZING coincidence).
wmam@sphinx.UChicago.UUCP (tony mason) (11/06/86)
In article <405@maynard.UUCP> campbell@maynard.UUCP (Larry Campbell) writes: >In article <347@prairie.UUCP> dan@prairie.UUCP (Daniel M. Frank) writes: >>In article <245@rabbit1.UUCP> barber@rabbit1.UUCP (Steve Barber) writes: >>>Another common problem is passing NULL as pointer argument. NULL is >>>#defined as 0, which is 2 bytes. Large model pointers are 4 bytes, so >>>the stack frame is now basically garbage. >> >> This isn't really true. Code in stdio.h for the SV/286 release >>checks your memory model, and if it is large, defines NULL to be 0L, >>which is the same size as a pointer. It doesn't please lint, so the >>best solution is still to cast it as appropriate (like (char *)0), >>but you ARE generally safe, as long as you include stdio.h. > >I wonder why stdio.h doesn't just declare NULL as "(char *) 0", or, >in the brave new world of ANSI X-whatever, "(void *) 0"? This should >do all the right things. Note that in SCO XENIX (a/k/a MICROSOFT XENIX) they have declared NULL to be of type (char *)0. Of course, you always have someone who will abuse this by doing something stupid such as: char buf[10]; buf[0] = NULL; but they will learn! The best practice is to cast it correctly (it sure makes lint happy!). Tony Mason > No opinions expressed here. Only cold hard University of Chicago > facts. uucp: ...ihnp4!gargoyle!sphinx!wmam, ...ihnp4!gargoyle!euler!tony bitnet: wmam%sphinx@UChicago.Bitnet US. Lotto System (bet your 22 cents that it will get there!!!) 3854 S. Archer (312) 254-2114 home Chicago, IL 60632
david@ukma.uky.csnet (David Herron, NPR Lover) (11/07/86)
In article <840@ur-valhalla.UUCP> dave@valhalla.UUCP (Dave Carlson) writes: >A potential problem I smacked into yesterday when porting BSD to SV/AT >is ioctl(2) expects as the third argument: >union { int iarg; > char *cparg;} >Problem is that the union will pull 4 bytes off the stack (in large model) >but the program calling with an integer will only push 2 bytes. Oh S*$&! >I cast my integer args long and everything seems ok but what a pain... Argh! And you're doing a port of an operating system??? UNIONS are the SAME size regardless of WHICH part of them you use! A user which passes an int to a routine expecting a union is ASKING for trouble! Argh! -- David Herron, cbosgd!ukma!david, david@UKMA.BITNET, david@ms.uky.csnet (I'm also "postmaster", "news", "netnews", "uucp", "mmdf", and ...) (And also the ACM chapter chairperson.) (And even an all-around nice guy. Aren't you lucky to get something from me?)
gwyn@brl-smoke.ARPA (Doug Gwyn ) (11/08/86)
In article <5068@ukme.ukma.uky.csnet> david@ukme.UUCP (David Herron, NPR Lover) writes: -In article <840@ur-valhalla.UUCP> dave@valhalla.UUCP (Dave Carlson) writes: ->A potential problem I smacked into yesterday when porting BSD to SV/AT ->is ioctl(2) expects as the third argument: ->union { int iarg; -> char *cparg;} ->Problem is that the union will pull 4 bytes off the stack (in large model) ->but the program calling with an integer will only push 2 bytes. Oh S*$&! ->I cast my integer args long and everything seems ok but what a pain... - -Argh! And you're doing a port of an operating system??? - -UNIONS are the SAME size regardless of WHICH part of them you use! - -A user which passes an int to a routine expecting a union is ASKING -for trouble! Oh, good grief! Mr. Carlson is talking about ioctl(), which is a well-known function whose third argument has a type that depends on its second argument's value; usually it's an (int) or a (struct termio *). The problem is not his; rather it is due to the SV/AT implementor changing ioctl()'s third argument to be a union. This is in violation of the SVID and of common sense, since (as Mr. Carlson reports) this breaks correctly-written code.