Tejas
Tejas

Reputation: 257

Allocate N size array inside a Shared memory

I have a structure

struct {
int size;
char *data;
}tmp_buf;

Now i want to allocate memory to the structure in shared memory (mmap-ed location)

i have a pointer "tp" of type "tmp_buf" in my main() When i try to use strncpy() something at location "tp->data" it gives a segmentation fault.

I have mmap-ed shared memory of size (sizeof(struct tmp_buf) + length_of_data)

This is the code i'm running:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/mman.h>

void * create_shared_memory(char *name, int size) {

    int *ptr;
    int ret;

    int fd = shm_open (name, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);

    if (fd == -1) {
        perror ("shm_open error!");
        exit (1);
    }

    ret = ftruncate (fd, sizeof (size));

    if (ret == -1) {
         perror ("ftruncate error!");
         exit (2);
    }

    ptr = mmap(0, sizeof (size), PROT_READ | PROT_WRITE,  MAP_SHARED, fd, 0);

    if (ptr == MAP_FAILED) {
        perror ("shm-mmap error!");
        exit (3);
    }

return ptr;

}

typedef struct {
        int size;
        char *data;

}tmp_buf;

int main (int argc, char **argv)
{
        tmp_buf *buf_ptr;
    if(argc != 2)
    {
        perror("Error: Incorrect number of arguments passed\n");
        exit(EXIT_FAILURE);
    }

        int max_buffers = atoi(argv[1]);
        buf_ptr = (struct tmp_buf*)create_shared_memory("my_shm_buffer",sizeof(tmp_buf) + max_buffers*1024);
        printf("Shared Memory Location: %p\n", buf_ptr);
        printf("Shared Memory size: %d\n", buf_ptr->size);
        printf("Shared Memory data: %s\n", buf_ptr->data);
        buf_ptr->size =1;
        printf("Shared Memory size: %d\n", buf_ptr->size);
        printf("SIZEOF(int) =%d SIZEOF(char*) = %d\n",sizeof(int), sizeof(char*));
        printf("Shared Memory size address: %p\n", (void*)&(buf_ptr->size));
        printf("Shared Memory data address: %p\n", (void*)&(buf_ptr->data));
        strncpy(buf_ptr->data,"Hello\n", 6);
        printf("Shared Memory data: %s\n", buf_ptr->data);
        return 0;
}

Output i am seeing is something like this :

Shared Memory Location: 0x7ffff7ff6000
Shared Memory size: 0
Shared Memory data: (null)
Shared Memory size: 1 (After t->size = 1)
Shared Memory size address: 0x7ffff7ff6000
Shared Memory data address: 0x7ffff7ff6008
Segmentation fault (core dumped) (After strncpy("Hello\n",tp->data, 6))

Upvotes: 0

Views: 391

Answers (2)

Antonin GAVREL
Antonin GAVREL

Reputation: 11239

Have you tried

strncpy(buf_ptr->data, "Hello\n\0", 7);

You should use strncpy with (dest, src, len) and not (src, dest, len)

The C library function char *strncpy(char *dest, const char *src, size_t n) copies up to n characters from the string pointed to, by src to dest. In a case where the length of src is less than that of n, the remainder of dest will be padded with null bytes.

Upvotes: 3

Chris Turner
Chris Turner

Reputation: 8142

The most obvious problem is demonstrated with this line:

ret = ftruncate (fd, sizeof (size));

sizeof(size) is not going to be very much as it'll be whatever sizeof(int) gives you. To make it the size you want you just pass in size as is like so...

ret = ftruncate (fd, size);

You then repeat the same problem with this line which should also have size instead of sizeof(size)

ptr = mmap(0, sizeof (size), PROT_READ | PROT_WRITE,  MAP_SHARED, fd, 0);

It's probably worth changing the function declaration to make size be of type size_t and have it return a tmp_buf *. Casting the void * returned won't automagically cause it to populate buf_ptr with valid values. End result should look like

tmp_buf* create_shared_memory(char *name, size_t size) {

    tmp_buf *ptr;
    int ret;

    int fd = shm_open (name, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);

    if (fd == -1) {
        perror ("shm_open error!");
        exit (1);
    }

    ret = ftruncate (fd, size);

    if (ret == -1) {
         perror ("ftruncate error!");
         exit (2);
    }

    ptr = mmap(0, size, PROT_READ | PROT_WRITE,  MAP_SHARED, fd, 0);

    if (ptr == MAP_FAILED) {
        perror ("shm-mmap error!");
        exit (3);
    }
    ptr->size = size;
    ptr->data = ((char *) ptr) + sizeof(ptr->size);

    return ptr;
}

Upvotes: 2

Related Questions