Segmentation fault on Linux (socket programming (TCP) in C)

I am just learning socket programming on Linux on some sites, and here are some pieces of my server side code using TCP:

#define BufferLength 100
#define SERVPORT 3111
int main()
{
  /* Variable and structure definitions. */
  int sd, sd2, rc, length = sizeof(int);
  int totalcnt = 0, on = 1;
  char temp;
  char buffer[BufferLength];
  struct sockaddr_in serveraddr;
  struct sockaddr_in their_addr;
  fd_set read_fd;

  /* Get a socket descriptor */
  if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  {
    perror("Server-socket() error");
    exit (-1);
  }
  else
    printf("Server-socket() is OK\n");

  /* Allow socket descriptor to be reusable */
  if((rc = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on))) < 0)
  {
    perror("Server-setsockopt() error");
    close(sd);
    exit (-1);
  }
  else
    printf("Server-setsockopt() is OK\n");

  /* bind to an address */
  memset(&serveraddr, 0x00, sizeof(struct sockaddr_in));
  serveraddr.sin_family = AF_INET;
  serveraddr.sin_port = htons(SERVPORT);
  serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
  printf("Using %s, listening at %d\n", inet_ntoa(serveraddr.sin_addr), SERVPORT);

  /* continue */
}

      

When I did the last line (printf ("using ......")) I got a segmentation fault, why? Thank.

+3


source to share


2 answers


The code as shown skips #include

any headers, so it won't compile due to some undefined characters.

However, it will compile if you only missed the prototype of any library functions referenced by the code, which would cause any function returned to be returned int

.

The latter fact may or may not be fatal.

On a 64-bit system, at least, it is fatal in the case inet_ntoa()

used as a parameter for printf()

, since on a 64-bit system, it is most likely expected to return a 64-bit value ( char

-pointer) (but 32bit int

). Thus (assuming that the prototypes miss) when generating the code, the compilers take inet_ntoa()

to return a 32-bit one int

, which will "chop" the most significant 32 bits of the returned address. Trying printf()

from such a "crippled" and therefore (most likely) invalid address causes undefined behavior and, in your case, results in the observed segmentation violation.



To fix this, add the appropriate prototype (for inet_ntoa()

) by adding:

#include <arpa/inet.h>

      

The compiler should have warned you about this. To enable all compiler warnings for gcc use options -Wall -Wextra -pedantic

. Serious warnings.

+3


source


It seems likely that inet_ntoa () returns NULL somehow, resulting in a segfault when dereferenced in printf (). I cannot find a direct link directly stating that this is possible with the Linux version of inet_ntoa, but I found several people who made this expression, and this is the only point in this code where a pointer is dereferenced.

The answer is at the bottom of this question: A segmentation fault for inet_ntoa states that inet_ntoa can return NULL. However, following his referenced links, I was unable to find an actual statement of this fact.



There is an MSDN article (which is suggestive, but certainly not directly related to Linux code) that explicitly states that inet_ntoa () can return NULL here: https://msdn.microsoft.com/en-us/library /windows/desktop/ms738564%28v=vs.85%29.aspx

0


source







All Articles