davis@pacific.mps.ohio-state.edu ("John E. Davis") (03/07/91)
Hi, The following code works on sun4 and ultrix but crashes on VMS. Just when I thought I understood pointers..... #include <stdio.h> void fm2(s) char **s; { *s = "Hello\n"; } void fm1(s) char **s; { char *ss; fm2(&ss); *s = ss; } int main() { char *s; fm1(&s); (void) fputs(s,stdout); return(0); } I expect to `hello' but I fail on VMS. I get a `symbolic dump stack ...'. What is wrong??? Thanks, -- John bitnet: davis@ohstpy internet: davis@pacific.mps.ohio-state.edu
scott@stl.stc.co.uk (Mike Scott) (03/07/91)
In the referenced article davis@pacific.mps.ohio-state.edu (John E. Davis) writes: >Hi, > > The following code works on sun4 and ultrix but crashes on VMS. Just when >I thought I understood pointers..... > (code omitted) >What is wrong??? > Works fine for me (VAXC 3.0-031, VMS 5.1-1 and VAXC v2.2-015, VMS 4.6). It would help everybody if anyone saying "it doesn't work" would give relevant version numbers...... -- Regards. Mike Scott STL, London Road, Harlow, Essex CM17 9NA, UK scott@stl.stc.co.uk <or> ...uunet!mcsun!ukc!stl!scott <or> PSI%234237100122::SCOTT phone +44-279-429531 xtn 3133.
tsm@genrad.UUCP (Thomas S. Morse) (03/07/91)
In article <DAVIS.91Mar6213546@pacific.mps.ohio-state.edu> davis@pacific.mps.ohio-state.edu (John E. Davis) writes: >Hi, > > The following code works on sun4 and ultrix but crashes on VMS. Just when >I thought I understood pointers..... > < deleted source > > >I expect to `hello' but I fail on VMS. I get a `symbolic dump stack ...'. >What is wrong??? I couldn't see anything wrong with your code so I ran it on my VAX station 2000 and it worked fine. Hope this helps, Tom
henry@zoo.toronto.edu (Henry Spencer) (03/08/91)
In article <DAVIS.91Mar6213546@pacific.mps.ohio-state.edu> davis@pacific.mps.ohio-state.edu (John E. Davis) writes: > The following code works on sun4 and ultrix but crashes on VMS. Just when >I thought I understood pointers..... > ... >int main() > { > ... > return(0); > } My tentative diagnosis is that you understand pointers but don't understand VMS exit status! 0 is *not* "success" in VMS. They're going to have to do something about this to conform to ANSI C, but they may not have figured that out yet. The pointer part of your program looks fine. -- "But this *is* the simplified version | Henry Spencer @ U of Toronto Zoology for the general public." -S. Harris | henry@zoo.toronto.edu utzoo!henry
gould@theory.tn.cornell.edu (EWD) (03/08/91)
In article <DAVIS.91Mar6213546@pacific.mps.ohio-state.edu> davis@pacific.mps.ohio-state.edu (John E. Davis) writes: >Hi, > > The following code works on sun4 and ultrix but crashes on VMS. Just when >I thought I understood pointers..... > ... > return(0); ... > >I expect to `hello' but I fail on VMS. I get a `symbolic dump stack ...'. >What is wrong??? It's been a while, but I believe the bottom line is that any useful C program on VMS must include a '$'. You need to #include some SYS$SYSDEF$DARKSIDEOFTHEFORCE file in some VMS specific include systax, then you have to #define your exit statuses in terms of the '$' infested constants therein, then you need to #define corresponding exit statuses for other platforms... But don't complain: The discipline will put you in Mr. Portable mode for the rest of your career. On the brighter side, at least on VMS you can walk and chew gum at the same time without the horrors of execles and sockets and children and signals. Give me a Unix with async io and endaction routines... Eliot W. Dudley edudley@rodan.acs.syr.edu RD 1, Box 66 Cato, New York 13033 315 437 0215
rankin@eql.caltech.edu (Pat Rankin) (03/08/91)
>In article <DAVIS.91Mar6213546@pacific.mps.ohio-state.edu> davis@pacific.mps.ohio-state.edu (John E. Davis) writes: > The following code works on sun4 and ultrix but crashes on VMS. > Just when I thought I understood pointers..... Your pointer usage looks correct. Are you using VAX C V3.0? Its optimizer had some problems with inlining functions. Try using ``cc/nooptimize'' or ``cc/opt=noinline'', or upgrade to V3.1 (which was released more than a year ago). You should always retry with optimization suppressed when something you're reasonably sure is correct gives the wrong results. >In article <1991Mar7.173712.18201@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes: > My tentative diagnosis is that you understand pointers but don't understand > VMS exit status! 0 is *not* "success" in VMS. He would have hit that next. Even ``return EXIT_SUCCESS;'' wouldn't help unless he defined EXIT_SUCCESS manually, because the the VAX C version of <stdlib.h> currently has the wrong value for VMS (it's 0, when VMS really does need 1 for success; it has 2 for EXIT_FAILURE, which is suitable but not optimal). In article <PJT.91Mar7191135@dharma.cpac.washington.edu>, pjt@cpac.washington.edu (Larry Setlow) writes... > I've redirected followups to comp.os.vms, since this line of > discussion has become VMS-specific. The question was about pointers, not about VMS. Exit status is a red herring here. Known compiler problems are appropriate for this group, as are suggestions to use EXIT_xx macros instead of hard coded exit values. Pat Rankin, rankin@eql.caltech.edu
scs@adam.mit.edu (Steve Summit) (03/09/91)
In article <1991Mar08.191107.23161@pilikia.pegasus.com> art@pilikia.pegasus.com (Art Neilson) writes: >In article <DAVIS.91Mar6213546@pacific.mps.ohio-state.edu> davis@pacific.mps.ohio-state.edu (John E. Davis) writes: ... >>void fm2(s) >>char **s; > ^ here we go yet again, this parameter doesn't match > what you're trying to pass in from fm1(). >>{ >> *s = "Hello\n"; > ^ you can't do this. s points nowhere. > besides, you need to do strcpy(s, "Hello"), > the way you are initializing *s is wrong. ... >> char *s; >> fm1(&s); > ^why are you passing "address of" s ? > s is already an address, remove the &. > >You should really read your textbook before posting something like this >to the net. Any book worth it's salt will teach you not to make the >sort of mistakes you've made here. Yes, it is important to make sure you understand what's going on before you post. The code posted by John Davis was correct, although it contained several (perfectly legal) pointers to pointers which apparently confused both a VMS compiler (thus John's original question) and Arthur Neilson (thus these irrelevant criticisms). The code passes lint -hbxa with flying colors (i.e. no complaints about argument mismatches) and runs correctly under any number of compilers. Steve Summit scs@adam.mit.edu
art@pilikia.pegasus.com (Art Neilson) (03/09/91)
In article <DAVIS.91Mar6213546@pacific.mps.ohio-state.edu> davis@pacific.mps.ohio-state.edu (John E. Davis) writes: >Hi, > > The following code works on sun4 and ultrix but crashes on VMS. Just when >I thought I understood pointers..... After seeing lots of replies to John Davis I went back and examined the program he posted again and realized I was wrong regarding his pointer usage, I sorta jumped the gun when I saw the &'s and ** stuff, I was wrong. I still don't think it's OK to assign the quoted string "Hello\n" to *s in fm2() as shown below. Where does *s point to ? Where in storage would "Hello\n" reside ? Does the compiler assign some scratch storage or something for it ?? >#include <stdio.h> >void fm2(s) >char **s; >{ > *s = "Hello\n"; >} -- Arthur W. Neilson III | INET: art@pilikia.pegasus.com Bank of Hawaii Tech Support | UUCP: uunet!ucsd!nosc!pilikia!art
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (03/10/91)
In article <1991Mar09.092611.24821@pilikia.pegasus.com> art@pilikia.pegasus.com (Art Neilson) writes: > I still don't think it's OK to assign the quoted string "Hello\n" > to *s in fm2() as shown below. Where does *s point to ? Where in storage > would "Hello\n" reside ? Does the compiler assign some scratch storage or > something for it ?? [ void fm2(s) char **s; { *s = "Hello\n"; } ] "Hello\n" is a constant string. When the compiler sees it, it makes room for it somewhere, and replaces "Hello\n" by a pointer to that location. Under UNIX, for example, the string is either stored along with the unwritable process text, or in the initialized data region, depending on your compiler. Now the string "Hello\n" has value <pointer to char,0x3753> if 0x3753 is the location where the compiler put "Hello\n". In fm2, s has type <pointer to pointer to char>. More precisely, say s has value <pointer to pointer to char,0x87654>. This means that at location 0x87654 there's a <pointer to char>, say <pointer to char,0x14702>. The assignment *s = "Hello\n" means ``Take s's value (a location in memory), and store a pointer to "Hello\n" in that location.'' In this case, that means to store <pointer to char,0x3753> at the location <object,pointer to char,0x87654>. The old value of *s, namely 0x14702, is replaced by a pointer to "Hello\n", namely 0x3753. So the string "Hello\n" is never copied. ``*s'' refers to a pointer-to-char object, and ``"Hello\n"'' has a pointer-to-char value. The assignment just stores the value inside the object. Chris will undoubtedly give a more comprehensible explanation. ---Dan
mla@enea.se (Mats L|fstr|m) (03/10/91)
In article <1991Mar08.191107.23161@pilikia.pegasus.com> art@pilikia.pegasus.com (Art Neilson) writes: Lots of stuff deleted, I haven't time to comment on all of it, so I'll concentrate on just one item. I think my point will be clear enough... >> >>int main() >> { >> char *s; >> >> fm1(&s); > ^why are you passing "address of" s ? > s is already an address, remove the &. s isn't an address, it's a pointer, i.e. a variable *containing* an address. And the poor guy is trying to give the address of this pointer as an argument to fm1(). Which is perfectly legal and very usefull in some situations. As in this, for instance. What he wants to do, is to give s a good value, i.e. set it to point to a "string". In order to do so, he must give the address of the pointer (s) as an argument to fm1(). fm1() then has a chance to change the value of s. Some more lines deleted. > >You should really read your textbook before posting something like this >to the net. Any book worth it's salt will teach you not to make the >sort of mistakes you've made here. Maybe you should buy yourself a new textbook. :-) >-- >Arthur W. Neilson III | INET: art@pilikia.pegasus.com >Bank of Hawaii Tech Support | UUCP: uunet!ucsd!nosc!pilikia!art ---------------------------------------------------------------------------- International: Domestic: Mats Lofstrom Mats L|fstr|m ENEA Data AB ENEA Data AB Nytorpsvagen 5b Nytorpsv{gen 5b Box 232 Box 232 S-183 23 TABY 183 23 T[BY Phone: (+46) 8792 - 2500 Tel: 08 - 792 25 00 e-mail: mla@enea.se ----------------------------------------------------------------------------
torek@elf.ee.lbl.gov (Chris Torek) (03/10/91)
In article <1991Mar09.092611.24821@pilikia.pegasus.com> art@pilikia.pegasus.com (Art Neilson) writes: >After seeing lots of replies to John Davis I went back and examined the >program he posted again and realized I was wrong regarding his pointer >usage, I sorta jumped the gun when I saw the &'s and ** stuff, I was >wrong. Indeed. (Incidentally, the reason his program `failed' on VMS was that he was testing a different program, an easy enough mistake to make; when he tested the one he posted, it worked.) >I still don't think it's OK to assign the quoted string "Hello\n" >to *s in fm2() as shown below. Where does *s point to ? Where in storage >would "Hello\n" reside ? Does the compiler assign some scratch storage or >something for it ?? If you do not know the answer to the latter question, you should not be posting definitive followups to comp.lang.c. A double quoted string in C is, with one exception%, an anonymous object of type `array N of char', where N is one more than the number of characters enclosed in quotes (after escape interpolation). The value of an array object is of course determined by The Rule, hence in >>#include <stdio.h> >>void fm2(s) >>char **s; >>{ >> *s = "Hello\n"; >>} the object at `*s' (which will have to be an <object, pointer to char> for the assignment to succeed) is made to point to the first character of this anonymous array of (in this case) 7 characters. That array itself resides in some sort of system-allocated space which has static storage duration; a typical system puts it in a code or initialized data segment. (There are atypical systems; a C compiler for Xerox D-machines once kept the original strings in Mesa `string descriptor' format and allocated the C versions on the heap. Perhaps it still does, although Xerox D-machines have largely been relegated to the Dustbin of History....) In the original example in question, `s' happened in this case to point to a single `char *' object declared in fm1(): fm1(ss) char **ss; { char *s; fm2(&s); *ss = s; } (I may have some of the original names mixed up), so the clause `which will have to be an <object, pointer to char> for the assignment to succeed' is satisfied. The object at fm2's `*s' is fm1's `s', so s is made to point to the `H' in `Hello\n\0'. Fm1 then sets the object at `*ss' (which has the exact same restriction) to point to that `H' as well, and fm1's *ss in the original example was main's `s', so everything was fine, if overly convoluted. ----- % The exception occurs when a double quoted string is used as an initializer for an object of type `array N of char' or `array N of const char', including when the size N is given as `the size of the initializer': char xyz[] = "abcd"; makes xyz an <object, array 5 of char, `abcd\0'>, and need not leave a copy of the sequence `abcd\0' anywhere else. (If it does leave a copy somewhere else, the compiler is wasting space, unless this copy exists for, e.g., debugging purposes.) -- In-Real-Life: Chris Torek, Lawrence Berkeley Lab EE div (+1 415 486 5427) Berkeley, CA Domain: torek@ee.lbl.gov
art@pilikia.pegasus.com (Art Neilson) (03/10/91)
In article <1991Mar9.073231.1364@athena.mit.edu> scs@adam.mit.edu writes: >In article <1991Mar08.191107.23161@pilikia.pegasus.com> art@pilikia.pegasus.com (Art Neilson) writes: >>In article <DAVIS.91Mar6213546@pacific.mps.ohio-state.edu> davis@pacific.mps.ohio-state.edu (John E. Davis) writes: >The code posted by John Davis was correct, although it contained >several (perfectly legal) pointers to pointers which apparently >confused both a VMS compiler (thus John's original question) and >Arthur Neilson (thus these irrelevant criticisms). The code >passes lint -hbxa with flying colors (i.e. no complaints about >argument mismatches) and runs correctly under any number of >compilers. Guess I deserve a bit of public chastisement for my criticisms. I still don't get why the string assignment *s = "Hello\n"; in fm2() is ok. Raymond Chen sent me an email stating that storage for "Hello\n" was allocated as static anonymous readonly by the compiler. I had always thought that the rvalue in a pointer assignment had to be an address. The usual way I do assignments of this nature is to either explicitly declare an array large enough to hold the string or malloc the storage and move the data there, or assign the pointer globally (outside of main) like: char *s = "Hello\n"; /* aggregate initializations out here */ main() { John's program does compile and run on my system ;^) (sheepish grin) so it must be ok. Since the assignment is ok, how large a string can be assigned in this manner ? Does the constant go in .data or .bss ?? -- Arthur W. Neilson III | INET: art@pilikia.pegasus.com Bank of Hawaii Tech Support | UUCP: uunet!ucsd!nosc!pilikia!art
ark@alice.att.com (Andrew Koenig) (03/10/91)
John E. Davis asked a question about pointers in C. Art Neilson reponded with a rather nasty criticism of the question. The trouble with this sort of criticism is that it can be embarrassing if the criticism is mistaken. Let's take a look at the original program and the criticism with an eye towards sorting it all out. In what follows, >> precedes comments by Davis (article <DAVIS.91Mar6213546@pacific.mps.ohio-state.edu>) and > precedes comments by Neilson (article <1991Mar08.191107.23161@pilikia.pegasus.com>). >> #include <stdio.h> >> void fm2(s) >> char **s; > ^ here we go yet again, this parameter doesn't match > what you're trying to pass in from fm1(). >> { >> *s = "Hello\n"; > ^ you can't do this. s points nowhere. > besides, you need to do strcpy(s, "Hello"), > the way you are initializing *s is wrong. > >> } Is it actually true that s points nowhere? It's hard to say without looking at the caller of fm2; we'll come to that presently. If we assume that s points somewhere, though, there is nothing wrong with saying *s = "Hello\n"; A string literal is essentially the "name" of an otherwise unnamed initialized character array. Thus the assignment above would make the pointer addressed by s point to the initial character of this array. That brings us back to the previous question: where does s point? Let's look at fm2's caller: >> void fm1(s) >> char **s; > ^ this formal parameter to fm1 doesn't match what > you're passing it from main. > >> { >> char *ss; >> fm2(&ss); > ^ here we go again. the & is not necessary. > >> *s = ss; >> } Aha! fm2 is passed the address of the local variable "ss" in function fm1. That variable is of type "char *" so its address is of type "char **", which matches the type of the formal parameter of fm2. Apparently that criticism is incorrect. We are now in a position to understand the assignment to *s in fm2; since s is the address of the variable ss in fm1, *s is that variable itself. Thus after executing this assignment, variable ss in fm1 will point to the initial character of "Hello\n". I see nothing wrong with that so far. Indeed, the second criticism in fm1 is also seen to be incorrect; the & is indeed necessary (else the call would not be type-safe) and the call fm2(&ss); has the same effect as ss = "Hello\n"; Now let's look at the first criticism in fm1, namely that the formal parameter to fm1 doesn't match what's passed from main. To check this, we need to look at main: >> int main() >> { >> char *s; >> >> fm1(&s); > ^why are you passing "address of" s ? > s is already an address, remove the &. > >> (void) fputs(s,stdout); >> return(0); >> } Variable s in main is of type "char *" so its address is of type "char **". That is the same type as the formal parameter to fm1, so the criticism of fm1 is incorrect. The criticism of "main" answers its own question: if fm1 were passed s rather than &s, the call would indeed be incorrect. What happens inside fm1? If we replace the call to fm2 by the assignment having the same effect, we get this: char *ss; ss = "Hello\n"; /* the effect of the call to fm2 */ *s = ss; What is *s? It's exactly the variable "s" in main. Thus, the effect of main should be as if its body were written: char *s; s = "Hello\n"; /* the effect of the call to fm1 */ (void) fputs(s,stdout); return(0); I don't see anything wrong with any of this, so I suspect a compiler bug. -- --Andrew Koenig ark@europa.att.com
gwyn@smoke.brl.mil (Doug Gwyn) (03/11/91)
In article <1991Mar09.092611.24821@pilikia.pegasus.com>, art@pilikia.pegasus.com (Art Neilson) writes: > Where does *s point to ? Where in storage would "Hello\n" reside ? The compiler must arrange for the string literal to be allotted some storage having static storage duration. There was nothing whatever wrong with the posted example program, just with the VMS C implementation, probably due to its failure to support 0 as a valid form for expressing a "successful" exit status.
ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (03/11/91)
In article <1991Mar08.191107.23161@pilikia.pegasus.com>, art@pilikia.pegasus.com (Art Neilson) set some kind of record for radically incorrect advice about John E. Davis's program #include <stdio.h> void fm2(s) char **s; { *s = "Hello\n"; } void fm1(s) char **s; { char *ss; fm2(&ss); *s = ss; } int main() { char *s; fm1(&s); (void) fputs(s,stdout); return(0); } Comrade Neilson ended by writing > You should really read your textbook before posting something like this > to the net. Any book worth it's salt will teach you not to make the > sort of mistakes you've made here. It really is _fitting_ that in advice more appropriately directed at the advisor the very common word "its" is spelled incorrectly. The program works correctly under "gcc -ansi -pedantic" and PCC. The only system-specific thing in it is the "return 0;" in main(). VMS has the convention that a program result signifies success (perhaps with a warning) if it is odd, failure if it is even. Recent versions of DCL have been taught to shut up about the error code 0, precisely to cope with sloppy C code, which may be why some people have reported that it works in VMS. Use EXIT_SUCCESS if you have it, if not #include <stdlib.h> #ifndef EXIT_SUCCESS #ifdef vms #define EXIT_SUCCESS 1 #else /* not vms */ #define EXIT_SUCCESS 0 #endif /* vms */ #endif /* EXIT_SUCCESS */ exit(EXIT_SUCCESS); /* instead of return 0; */ -- The purpose of advertising is to destroy the freedom of the market.
gwyn@smoke.brl.mil (Doug Gwyn) (03/12/91)
In article <4934@goanna.cs.rmit.oz.au> ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes: >The only system-specific thing in it is the "return 0;" in main(). Even that is strictly conforming to the C standard.
jockc@hammer.idsila.com (PRIV Account) (03/12/91)
In article <1991Mar10.040429.29309@pilikia.pegasus.com> art@pilikia.pegasus.com (Art Neilson) writes: > ..discussion deleted.. >Guess I deserve a bit of public chastisement for my criticisms. >I still don't get why the string assignment > > *s = "Hello\n"; > >in fm2() is ok. Raymond Chen sent me an email stating that storage for >"Hello\n" was allocated as static anonymous readonly by the compiler. >I had always thought that the rvalue in a pointer assignment had to be an >address. The usual way I do assignments of this nature is to either >explicitly declare an array large enough to hold the string or malloc Think of it like this: main() { int x=1; foo(x); printf("%d\n",x); /*prints 1*/ bar(&x); printf("%d\n",x); /*prints 5*/ return 0; } foo(val) int val; { val=5; } bar(val) int *val; { *val=5; } For a function to modify the varable I pass it, I have to pass it's address. The same goes for a char pointer. I must pass the address so that the called function can change its contents: main() { char *s="some chars"; foo(s); printf("%s\n",s); /* prints "some chars" */ bar(&s); printf("%s\n",s); /* prints "different chars" */ } foo(str) char *str; { str="different chars"; /* this changes this function's copy of the passed variable's value */ } bar(str) char **str; { *str = "different chars"; }
ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (03/12/91)
In article <15439@smoke.brl.mil>, gwyn@smoke.brl.mil (Doug Gwyn) writes: > In article <4934@goanna.cs.rmit.oz.au> ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes: > >The only system-specific thing in it is the "return 0;" in main(). > > Even that is strictly conforming to the C standard. I didn't say it was *non-standard*, I said it was *system-specific*. There are a lot of pre-ANSI C compilers out there, and I have met ones where "return 0;" in the main program did not work at all. I didn't say that the VAX/VMS C compiler doesn't like it either. My point was simply that ANSI or not, one may run into compilers where it doesn't work, so one might as well play safe and stick with exit(). -- The purpose of advertising is to destroy the freedom of the market.