Segfault (possibly due to casting)
I don't normally go to stackoverflow for sigsegv errors, but I have done all I can with my debugger at the moment.
The segmentation fault error is thrown following the completion of the function. Any ideas what I'm overlooking? I suspect that it is due to the casting of the sockaddr to the sockaddr_in, but I am unable to find any mistakes there. (Removing that line gets rid of the seg fault -- but I know that may not be the root cause here).
// basic setup
int sockfd;
char str[INET_ADDRSTRLEN];
sockaddr* sa;
socklen_t* sl;
struct addrinfo hints, *servinfo, *p;
int rv;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;开发者_StackOverflow
// return string
string foundIP;
// setup the struct for a connection with selected IP
if ((rv = getaddrinfo("4.2.2.1", NULL, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return "1";
}
// loop through all the results and make a socket
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("talker: socket");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "talker: failed to bind socket\n");
return "2";
}
// connect the UDP socket to something
connect(sockfd, p->ai_addr, p->ai_addrlen); // we need to connect to get the systems local IP
// get information on the local IP from the socket we created
getsockname(sockfd, sa, sl);
// convert the sockaddr to a sockaddr_in via casting
struct sockaddr_in *sa_ipv4 = (struct sockaddr_in *)sa;
// get the IP from the sockaddr_in and print it
inet_ntop(AF_INET, &(sa_ipv4->sin_addr), str, INET_ADDRSTRLEN);
printf("%s\n", str);
// return the IP
return foundIP;
}
It doesn't look like you ever initialize the pointer sa
to point at a valid sockaddr
(or sockaddr_in
) object.
If you replace
sockaddr* sa;
with
sockaddr addr;
and replace all uses of sa
with &addr
you should be in better shape.
The same is also true of sl
. At least according to the documentation for my getsockname the socklen_t*
parameter needs to point at a valid socklen_t
object initialized to the size in bytes of the address buffer.
E.g.
socklen_t slen = sizeof addr;
and use &slen
instead of sl
.
It looks to me like you don't ever set up the sa pointer to actually point at anything. Commenting out the line "struct sockaddr_in *sa_ipv4 = (struct sockaddr_in *)sa;" should cause a compile error, so I guess I can see how not being able to compile your program would also cause it to not segfault - hard for a non-existent binary to crash :)
just to add, valgrind is pretty useful in detecting uninitialized pointers or for that matter any pointer related errors.
You did not allocate sa
before passing it to getsockname
, so you effectively passed in some garbage pointer value there. It needs to be:
struct sockaddr_in sa;
socklen_t sl;
...
getsockname(sockfd, (struct sockaddr*)&sa, &sl);
...
精彩评论