Search code examples
cmemory-managementsegmentation-faultvalgrindmmap

mmap() causing segmentation fault in C


I'm pretty sure my mistake is very evident, but I just can't seem to find where the problem is.

I'm learning how to use mmap() in C, everything looks correct to me, but I get a segmentation fault.

Here is my code:

int n=50;
char * tab = mmap(NULL, n, PROT_READ | PROT_WRITE, MAP_SHARED, -1, 0);

for(int i=0; i<n; i++)
{
   tab[i] = 1;
}

Using valgrind, I get an error saying "Invalid write of size 1" at the line where I do tab[i]=1, (I have tried replacing 1 by '1' thinking that maybe a char has a smaller size than an int, but still get the same error), followed by "Address 0xfffff..ff is not stack'd, malloc'd, or (recently) free'd".

I have no idea where my mistake is. Can somebody help me find it?


Solution

  • From man 2 mmap:

    The contents of a file mapping (as opposed to an anonymous mapping; see MAP_ANONYMOUS below), are initialized using length bytes starting at offset offset in the file (or other object) referred to by the file descriptor fd.

    I suppose that you are trying to create an anonymous mapping (i.e. not backed by a file). In such case, you need to add MAP_ANONYMOUS to the flags, otherwise the system will try to read from the specified fd, which is invalid (-1) and will fail.

    The correct code is:

    char *tab = mmap(NULL, n, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    if (tab == MAP_FAILED) {
        perror("mmap");
        exit(1);
    }
    

    For the future, note that you can easily detect the error like I did above with a simple call to perror() in case the returned value indicates failure. In your case it should have printed the following:

    mmap: Bad file descriptor
    

    Checking the manual again you can see in the "ERRORS" section:

    EBADF: fd is not a valid file descriptor (and MAP_ANONYMOUS was not set).