Really odd pointer behavior

M

Mr. X

Hello all,

Please advise...

Consider the following...

void init_sockaddr (struct sockaddr_in *name, const char *hostname,int port)
{
struct hostent *hostinfo;
name->sin_family = AF_INET;
name->sin_port = htons (port);
hostinfo = gethostbyname (hostname);

#if ONEWAY
name->sin_addr = *(struct in_addr *) hostinfo->h_addr;
#endif

#if ANOTHERWAY
bcopy(hostinfo->h_addr, (char*)&(name->sin_addr), hostinfo->h_length);
#endif
}

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.

My bigger concern is why it even compiles?
What is the "*" to the left of the "(" in that line?
What is it doing?
Admittedly, it was a mistake that worked, but I am more interested
in
 
R

Ravi Uday

void init_sockaddr (struct sockaddr_in *name, const char *hostname,int port)
{
struct hostent *hostinfo;
name->sin_family = AF_INET;
name->sin_port = htons (port);
hostinfo = gethostbyname (hostname);

#if ONEWAY
name->sin_addr = *(struct in_addr *) hostinfo->h_addr;
#endif

#if ANOTHERWAY
bcopy(hostinfo->h_addr, (char*)&(name->sin_addr), hostinfo->h_length);
#endif
}

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.
You mean once the function reaches its end / returns, in which case Yes
information
in the 'hostinfo' is lost.
My bigger concern is why it even compiles?

Whats wrong in compiling ? Its common to declare local variables only to use
it locally inside
the function and once you return from the function you forget about those..
What is the "*" to the left of the "(" in that line?
What is it doing?
* -> dereferencing pointer.
It dereferences the value in hostinfo->h_addr and assigns to name->sin_addr
(input parameter)
 
B

Barry Margolin

"Mr. X said:
Hello all,

Please advise...

Consider the following...

void init_sockaddr (struct sockaddr_in *name, const char *hostname,int port)
{
struct hostent *hostinfo;
name->sin_family = AF_INET;
name->sin_port = htons (port);
hostinfo = gethostbyname (hostname);

#if ONEWAY
name->sin_addr = *(struct in_addr *) hostinfo->h_addr;
#endif

#if ANOTHERWAY
bcopy(hostinfo->h_addr, (char*)&(name->sin_addr), hostinfo->h_length);
#endif
}

As I understand, there will be problems with the first way.
Because once the CPU leaves the function, hostinfo might be lost.

So? You've copied the data out of it into the structure that name
points to, so you don't care about hostinfo any more.
For now, it works, but I imagine it might one day fail.

My bigger concern is why it even compiles?
What is the "*" to the left of the "(" in that line?
What is it doing?

It's indirecting through the pointer. hostinfo->h_addr is an array,
which is automatically converted to a pointer in this context. (struct
in_addr *) casts that pointer to a pointer to an in_addr structure. The
* at the beginning means to access the contents of the structure that it
points to, so this structure is copied into name->sin_addr.
 
D

Dave Thompson

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,145
Messages
2,570,826
Members
47,371
Latest member
Brkaa

Latest Threads

Top