|
From: Sune A. <sun...@ho...> - 2012-01-14 04:34:22
|
Hi!
I'm writing the following in what will become a TCP client:
>>>>>>>>>>>>>>>>>>>>>
struct sockaddr_in daemon_addr;
/* Connect to localhost */
daemon_addr.sin_family = AF_INET;
daemon_addr.sin_port = htons((*conn)->daemon_port);
daemon_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
memset(&(daemon_addr.sin_zero), 0, sizeof daemon_addr.sin_zero);
if ((rc = connect(fd, (struct sockaddr *)&daemon_addr, sizeof(struct sockaddr))) < 0) {
/* error */
}
<<<<<<<<<<<<<<<<<<<<<
...and I get the error message:
Syscall param socketcall.connect(serv_addr.sin_port) points to uninitialised byte(s)
==4388== at 0x52C2340: __connect_nocancel (syscall-template.S:82)
I don't understand why?
Thanks in advance
/Sune |
|
From: John R. <jr...@bi...> - 2012-01-14 05:52:06
|
On 01/13/2012 08:34 PM, Sune Ahlgren wrote:
> I'm writing the following in what will become a TCP client:
>
>>>>>>>>>>>>>>>>>>>>>>
>
> struct sockaddr_in daemon_addr;
>
>
> /* Connect to localhost */
> daemon_addr.sin_family = AF_INET;
> daemon_addr.sin_port = htons((*conn)->daemon_port);
> daemon_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
> memset(&(daemon_addr.sin_zero), 0, sizeof daemon_addr.sin_zero);
>
> if ((rc = connect(fd, (struct sockaddr *)&daemon_addr, sizeof(struct sockaddr))) < 0) {
> /* error */
> }
>
> <<<<<<<<<<<<<<<<<<<<<
>
> ...and I get the error message:
> Syscall param socketcall.connect(serv_addr.sin_port) points to uninitialised byte(s)
> ==4388== at 0x52C2340: __connect_nocancel (syscall-template.S:82)
Please state which version of glibc you are using (ls -l /lib*/libc-*).
Notice that your code called 'connect(', but the complaint is from a call
to 'socketcall.connect('. There is only one actual system call 'socketcall',
and the routines bind(), connect(), listen(), select(), etc., are multiplexed
into that one syscall via the second parameter "struct sockaddr *".
Look closely at the complete traceback from the complaint.
Also, inspecting the definition of "struct sockaddr" in <bits/socket.h>
and <bits/sockaddr.h> and <netinet/in.h> hints at usage of variable-length arrays
and unions:
-----
#define __SOCKADDR_COMMON(sa_prefix) \
sa_family_t sa_prefix##family
struct sockaddr
{
__SOCKADDR_COMMON (sa_); /* Common data: address family and length. */
char sa_data[14]; /* Address data. */
};
struct sockaddr_in
{
__SOCKADDR_COMMON (sin_);
in_port_t sin_port; /* Port number. */
struct in_addr sin_addr; /* Internet address. */
/* Pad to size of `struct sockaddr'. */
unsigned char sin_zero[sizeof (struct sockaddr) -
__SOCKADDR_COMMON_SIZE -
sizeof (in_port_t) -
sizeof (struct in_addr)];
};
-----
So there is plenty of room for disagreement over exactly which bytes
should be considered to be initialized at exactly which step in
the execution of 'connect('. In order to disambiguate what is
going on, it is necessary to single-step each instruction while
tracking through the source code of glibc. If parsing is required
to interpret the data in .sin_port, then that is likely to be part
of the problem because memcheck has no knowledge of what the
representation means. Also, it would be safer for your code
to zero _all_ of daemon_addr first, then [over-]write various fields.
--
|
|
From: John R. <jr...@bi...> - 2012-01-14 14:12:41
|
On 01/13/2012 11:07 PM, Sune Ahlgren wrote: > Thanks for your input. > > By adding --track-origins=yes to Memcheck I was able to pin-point the issue. > > Valgrind rocks!!! Other users would appreciate reading what you learned. Using --track-origins=yes is powerful. The result of applying that parameter to this case is instructive, too. Please send a short explanation to the [valgrind-users] list. Thank you. -- |