Re: Really odd pointer behavior
From: Dave Thompson (david.thompson1_at_worldnet.att.net)
Date: 08/04/04
- Next message: Old Wolf: "Re: Is "C For Dummies" any good?"
- Previous message: Dave Thompson: "Re: Calc checksum of certain ELF sections"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Wed, 04 Aug 2004 03:30:21 GMT
On Thu, 29 Jul 2004 18:44:55 -0700, "Mr. X" <greenbaboon1@cox.net>
wrote:
> Hello all,
>
> Please advise...
>
> Consider the following...
>
> void init_sockaddr (struct sockaddr_in *name, const char *hostname,int port)
In standard C int may be as little as 16-bits signed, which -max or -0
excluded, hence unable to correctly represent all 16-bit port numbers
used in IP. The correct type for a port number, and for an argument to
htons, is unsigned short, or more formally uint16_t which almost
always will be typedef'ed to unsigned short.
> {
> struct hostent *hostinfo;
> name->sin_family = AF_INET;
> name->sin_port = htons (port);
> hostinfo = gethostbyname (hostname);
>
Should check hostinfo is non-null befure using it; there are lots of
reasons gethostbyname can fail, in which cases it returns null.
> #if ONEWAY
> name->sin_addr = *(struct in_addr *) hostinfo->h_addr;
> #endif
>
This could fail if hostinfo->h_addr points to memory that is not
correctly aligned for a struct in_addr; what alignment is required, if
any, is platform dependent. In practice it likely will be, given the
variety of ways the provider may need to construct it, but I don't
believe anything (in particular SUS/POSIX) guarantees it.
> #if ANOTHERWAY
> bcopy(hostinfo->h_addr, (char*)&(name->sin_addr), hostinfo->h_length);
> #endif
bcopy is not standard C, although it is likely to be available on
(most? all?) systems that have (BSDish) sockets. memcpy is, and takes
pointers to void which are converted automatically without casting.
That is the approach guaranteed to work always. Well, as long as the
implementation has a correct <netdb.h>, <arpa/inet.h>, gethostbyname,
etc. which as far as the C standard is concerned could so something
completely different from their normal Unix/sockets meaning.
> }
>
> As I understand, there will be problems with the first way.
> Because once the CPU leaves the function, hostinfo might be lost.
> For now, it works, but I imagine it might one day fail.
>
Not for that reason. Yes, the pointer hostent is local to this
function and lost when it returns, and more to the point, as it were,
what it points to, i.e. the value returned from successful gethostY,
plus the data pointed to by h_addr_list and h_addr (which is
h_addr_list[0] on modern systems) may be overwritten by other getX et
al. But you have already copied the data to the sockaddr_in provided
by the caller when this function returns so those don't matter, except
for thread-unsafety if in a multithread environment.
> My bigger concern is why it even compiles?
> What is the "*" to the left of the "(" in that line?
> What is it doing?
That is taking h_addr (which as noted is really h_addr_list[0]), which
is a pointer to void, which means effectively "unspecified" type, and
casting it to a pointer to in_addr, which is what the data provided by
gethostbyname actually is, and *(cast)ptr fetches that data, which is
then stored in (assigned to a field of) the caller-provided struct.
> Admittedly, it was a mistake that worked, but I am more interested
> in
>
- David.Thompson1 at worldnet.att.net
- Next message: Old Wolf: "Re: Is "C For Dummies" any good?"
- Previous message: Dave Thompson: "Re: Calc checksum of certain ELF sections"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|