[comp.unix.programmer] Return value from shmat

newsuser@oliver.SUBLINK.ORG (Ugo Cei) (05/07/91)

[This is crossposted to comp.lang.c, since the discussion on the
pointer/integer relationship may have a wider audience than just Unix
programmers.]

From a typical SysV shmat(2) man page:

|	  char *shmat (shmid, shmaddr, shmflg)
|	  int shmid;
|	  char *shmaddr;
|	  int shmflg;

[...]

|     Diagnostics
|	  Upon successful completion, the return value is as follows:
|
|	       shmat returns the data segment start address of the
|	       attached	shared memory segment.
|
|	       shmdt returns a value of	0.
|
|	  Otherwise, a value of	-1 is returned,	and errno is set to
|	  indicate the error.

I have always believed that comparing pointers to integers was not
portable, unless the integer is the constant 0 (which is not an
integer at all, in this context). Well, if you concede me this, how am
I supposed to test for the failure or success of shmat(2) ? Maybe:

	char * shmaddr;
	if((shmaddr = shmat(shmid, shmaddr, shmflg)) < 0)
		...

This, however, elicits a severe warning from my compiler, since I am
not supposed to do an ordered comparison of a pointer and an integer.
This is an issue that I wholeheartedly agree with. 

In the end, I have resorted to this kind of kludge:

	if((shmaddr = shmat(shmid, shmaddr, shmflg)) == (char *)(~0))
		...

I know, this is not portable either, but my eyes are much more pleased
since this resembles ``... == (char *) 0'', which IS portable. And
even my compiler has stopped complaining. Now, my question is: why on
earth wasn't shmat(2) made to return 0 (NULL) in case of failure ? Are
there some subtle reasons for this that I am not aware of ?

Inquiring mind wants to know.




-- 
**************** | Ugo Cei            | home:    newsuser@oliver.sublink.org
*    OLIVER    * | Via Colombo 7      | office:  cei@ipvvis.unipv.it
**************** | 27100 Pavia ITALY  |       "Real Programs Dump Core"

steve@taumet.com (Stephen Clamage) (05/08/91)

newsuser@oliver.SUBLINK.ORG (Ugo Cei) writes:

>From a typical SysV shmat(2) man page:

>|	  char *shmat (shmid, shmaddr, shmflg) ...

>|     Diagnostics
>|	  ...
>|	  Otherwise, a value of	-1 is returned ...

>I have always believed that comparing pointers to integers was not
>portable, unless the integer is the constant 0 (which is not an
>integer at all, in this context).

Correct.

The man page says that -1 is returned, not ~0, so just compare the return
to -1, suitably cast:
	if((shmaddr = shmat(shmid, shmaddr, shmflg)) == (char *)(-1))

I would not be overly concerned with portability on this, since it is
a Unix-specific issue.  This code should work on any system supplying
shmat.
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

allbery@NCoast.ORG (Brandon S. Allbery KB8JRR/AA) (05/11/91)

As quoted from <986@oliver.SUBLINK.ORG> by newsuser@oliver.SUBLINK.ORG (Ugo Cei):
+---------------
| I know, this is not portable either, but my eyes are much more pleased
| since this resembles ``... == (char *) 0'', which IS portable. And
| even my compiler has stopped complaining. Now, my question is: why on
| earth wasn't shmat(2) made to return 0 (NULL) in case of failure ? Are
| there some subtle reasons for this that I am not aware of ?
+---------------

Not so subtle:  ALL system calls return -1 on failure.  No exceptions.  This
is generally handled by assembly language glue in libc.a (the versions of Unix
whose assembler calling conventions I'm familiar with set the "carry" flag to
indicate an error on return from a system call).

In any case, the return value from shmat() is not "portable" anyway, because I
may not want a (char *).  I have a program which uses it as a (double *), for
example.  Now, as it turns out, alignment is guaranteed by the default calling
sequence (you can pass flags to shmat() which can affect this, but the default
is suitably aligned for any type), but it's notoriously difficult to explain
this to C, which is why (void *) was invented.

++Brandon
-- 
Me: Brandon S. Allbery			  Ham: KB8JRR/AA  10m,6m,2m,220,440,1.2
Internet: allbery@NCoast.ORG		       (restricted HF at present)
Delphi: ALLBERY				 AMPR: kb8jrr.AmPR.ORG [44.70.4.88]
uunet!usenet.ins.cwru.edu!ncoast!allbery       KB8JRR @ WA8BXN.OH