Yaser Jaradeh
Yaser Jaradeh

Reputation: 322

How to define 2D array of characters in C Linux using shared memory and fill it with chars

I am using Eclipse C/C++ IDE on Ubuntu and am trying to define a 2D of char as a shared memory between a parent-child processes and am using this :

void fill(char **p)
{
    printf ("int i=0;\n");
    int i=0;
    printf ("int j=0;\n");
    int j=0;
    for(i=0;i<3;i++)
    {
        for(j=0;j<3;j++)
        {
            p[i][j]=' ';
        }
    }
}


int shmid;
char **shmPtr;
if(shmid = shmget(2000, sizeof(char[3][3]), 0)!=-1)
{
    shmPtr = shmat(shmid, 0, 0); //attach shared memory to pointer
    fill(shmPtr);
}

Is this the right way to define the array or not? While trying to fill this array I get a

segmentation fault

.

Upvotes: 0

Views: 3583

Answers (2)

MatheusOl
MatheusOl

Reputation: 11835

When working with shared memory (actually dynamic allocated in general) I'd recommend you to use use the following arithmetic to access 2D data instead of "[i][j]":

*(pointer + row * ncols + col) = ...

Also, you should use character ' ' instead of the string " " (which is a const char*).In your sample, the fill function would be something like:

void fill(char *p, int rows, int cols)
{
    int i, j;
    for(i=0; i<rows; i++)
    {
        for(j=0;j<cols;j++)
        {
            /* p[i][j] = ' '; */
            *(p + i*cols + j) = ' ';
        }
    }
}

Another, even better, is to use memset:

void fill(char *p, int rows, int cols)
{
    memset(p, (int)' ', cols*rows);
}

And, a main sample:

int main()
{
    int shmid;
    void *shmPtr;
    char *shm;
    /* create the shared segment */
    if ((shmid = shmget(IPC_PRIVATE, sizeof(char) * (3*3), IPC_CREAT | 0666)) < 0) {
        perror("shmget");
        exit(1);
    }
    /* use it on the parent process */
    if ((shmPtr = shmat(shmid, NULL, 0)) == (char *) -1) {
        perror("shmat");
        exit(1);
    }
    shm = (char *)shmPtr;
    /* fill with spaces */
    fill(shmPtr, 3, 3);
    int i;
    /* some forks, sample */
    for (i = 0; i < 10; i++) {
        if (fork() == 0) {
                ... child workd ...
        }
    }
    ...
    shmctl(shmid, IPC_RMID, NULL);
    return 0;
}

One more thing, if possible, try using mmap instead of the SysV shared memory.

Upvotes: 0

user529758
user529758

Reputation:

Just what I suspected. Two-dimensional arrays ain't double pointers.

void fill(char p[3][3])
{
    int i, j;
    for (i = 0; i < 3; i++) {
        for (j = 0; j < 3; j++) {
            p[i][j] = ' ';
        }
    }
}

int shmid = shmget(2000, sizeof(char[3][3]), 0);
char (*shmPtr)[3] = shmat(shmid, 0, 0);
fill(shmPtr);

Upvotes: 1

Related Questions