clinux

read fails with EFAULT


I am running the following C code, where trying to read in buffer which is allocated on caller's stack, but fails with errno 14 (Bad Address).

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>

void wrapper(int fd, char **buf)
{
  int res = read(fd, *buf, 10);

  printf("res: %d, errno: %d\n", res, errno);

  printf("Buf: %s\n", *buf);
}

int main()
{
  char buffer[10];

  memset(buffer, 0, 10);

  int fd = open("main.c", O_RDONLY);

  wrapper(fd, (char **)&buffer);

  return 0;
}

The output is

res: -1, errno: 14
Buf: (null)

I have been searching for explanation why it fails, whereas changing it to

void wrapper(int fd, char *buf)
...
wrapper(fd, (char *)buffer);

works, but without result so far.


Solution

  • why it fails

    Arrays are not pointers. buffer is not a char*. It's a char[10]. It will decay to char* in many contexts, but not in the specific context of taking its address. Consequently, &buffer is not a char**, is not compatible with char**, and should not be cast to char**. If it is cast to char** and then dereferenced, the behaviour is undefined.