Sean Kelly Sean Kelly - 1 month ago 11
C Question

Using mmap() instead of malloc()

I am trying to complete an exercise that is done with system calls and need to allocate memory for a struct *. My code is:

myStruct * entry = (myStruct *)mmap(0, SIZEOF(myStruct), PROT_READ|PROT_WRITE,
MAP_ANONYMOUS, -1, 0);


To clarify, I cannot use
malloc()
but can use
mmap()
. I was having no issues with this on Windows in Netbeans, now however I'm compiling and running from command line on Ubuntu I am getting "Segmentation Fault" each time I try to access it.

Is there a reason why it will work on one and not the other, and is
mmap()
a valid way of allocating memory in this fashion? My worry was I was going to be allocating big chunks of memory for each
mmap()
call initially, now I just cannot get it to run.

Additionally, the error returned my mmap is 22 - Invalid Argument (I did some troubleshooting while writing the question so the error check isn't in the above code). Address is 0, the custom
SIZEOF()
function works in other mmap arguments, I am using
MAP_ANONYMOUS
so the
fd
and
offset
parameters must -1 and 0 respectively.

Is there something wrong with the
PROT_READ|PROT_WRITE
sections?

Answer

You need to specify MAP_PRIVATE in your flags.

myStruct * entry = (myStruct *)mmap(0, SIZEOF(myStruct),
        PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);

From the manual page:

The flags argument determines whether updates to the mapping are visible to other processes mapping the same region, and whether updates are carried through to the underlying file. This behavior is determined by including exactly one of the following values in flags:

You need exactly one of the flags MAP_PRIVATE or MAP_SHARED - but you didn't give either of them.

A complete example:

#include <sys/mman.h>
#include <stdio.h>

typedef struct
{
    int a;
    int b;
} myStruct;

int main()
{
    myStruct * entry = (myStruct *)mmap(0, sizeof(myStruct),
            PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

    if (entry == MAP_FAILED) {
        printf("Map failed.\n");
    }
    else {
        entry->a = 4;
        printf("Success: entry=%p, entry->a = %d\n", entry, entry->a);
    }
    return 0;
}

(The above, without MAP_PRIVATE of course, is a good example of what you might have provided as a an MCVE. This makes it much easier for others to help you, since they can see exactly what you've done, and test their proposed solutions. You should always provide an MCVE).

Comments