3

More or less what it says in the title. I have a call to getaddrinfo like so:

struct addrinfo crossplat, *actual_addr;
crossplat.ai_family = AF_UNSPEC; //IPv4 or IPv6.
crossplat.ai_socktype = SOCK_STREAM; 

if(int i = getaddrinfo("localhost", "8000", &crossplat, &actual_addr)!=0){
    cerr << "error code " << i << " received. Meaning: "<<  gai_strerror(i) << endl;
    return -1;
}

Which proudly prints:

error code 1 received. Meaning: Unknown error

on my system.

The getaddrinfo man page on my system:

RETURN VALUE
   getaddrinfo() returns 0 if it succeeds, or one of the following 
   nonzero error codes:

   EAI_ADDRFAMILY....


   ...The gai_strerror() function translates these error codes to a 
       human readable string, suitable for error reporting.

Which suggests to me that all non-zero codes returned by getaddrinfo should be one of the listed EAI_* family codes. Searching online suggests that gai_strerror() will only return "Unknown error" when it is passed an error code which is not a member of the EAI_* family, which would seem to rule out "1" being such a code.

Apparently I'm doing something rather wrong here, so any assistance would be greatly appreciated!

simonc
  • 41,632
  • 12
  • 85
  • 103
John Doucette
  • 4,370
  • 5
  • 37
  • 61

3 Answers3

7

This expression is a syntax error in C, but assuming you are using C++ it's not grouped how you're expecting:

if (int i = getaddrinfo("localhost", "8000", &crossplat, &actual_addr)!=0){

This will assign the result of getaddrinfo("localhost", "8000", &crossplat, &actual_addr) != 0 to i, which is always either 0 or 1. Any non-zero return by getaddrinfo() will leave i with the value of 1.

You need to declare i earlier so that you can paranthesize the assignment:

int i;
if ((i = getaddrinfo("localhost", "8000", &crossplat, &actual_addr)) != 0) {

(of course, having done this you'd probably also move the getaddrinfo() call to the initializer of i).

caf
  • 233,326
  • 40
  • 323
  • 462
  • Ah, that's done it nicely. I usually write C, but have to compile with g++ for this project, which led me to take advantage of poorly understood features. Thanks for the info! – John Doucette Nov 15 '12 at 11:51
  • 2
    @JohnDoucette Using assignment inside conditions is a very effective way to generate hard-to-find bugs. – Lundin Nov 15 '12 at 11:52
2

I think you'll need to initialise crossplat.ai_protocol. The man page section on the hints argument mentions this being used in addition to the addrinfo members you already initialise.

You might also need to initialise crossplat.ai_flags. It'd probably be easier to just memset the whole structure:

struct addrinfo crossplat, *actual_addr;
memset(&crossplat, 0, sizeof(crossplat));
crossplat.ai_family = AF_UNSPEC; //IPv4 or IPv6.
crossplat.ai_socktype = SOCK_STREAM;
simonc
  • 41,632
  • 12
  • 85
  • 103
1

In getaddrinfo.h : #define EAI_ADDRFAMILY 1, which means : address family for hostname not supported

Waterfrag
  • 517
  • 4
  • 20
  • Interesting, but if this is the case, why doesn't gai_strerror correctly translate it on my system? – John Doucette Nov 15 '12 at 11:00
  • don't know exactly, but in gai_strerror() man page EAI_ADDRFAMILY ins't listed, even if it is defined in netdb.h. Maybe it ignores the error but that would be strange... – Waterfrag Nov 15 '12 at 11:07
  • The value of `EAI_ADDRFAMILY` varies for different C libraries - for example for mine it is -9. – caf Nov 15 '12 at 11:18