Question

I'm a student working on a simple C program that implements two shared memory segments. The thing is that when I use strcpy function with the pointer to the second memory segment called nptr2 changes the value of the firt memory segment with the name nptr.

I've been reading another questions that were solved putting nulls at the end of the string because the string that was being copied had not a null terminating caracter. But I expect that's not my case, as I'm using fgets. I'm showing you the output of some printf I've added to my code to see easier what's happening.

Struct used for nptr

struct estadistikak{
int erabiltzaile;
int bbluzera;
int mezukop;
int karakkop;
};

Memory segment declarations and attachments

int memid,memid2;
char mezua[50],*nptr2;
struct shmid_ds buff;
struct estadistikak *nptr;

if ((memid=shmget(0x1234L,sizeof(mezua),0600|IPC_CREAT))<0){
    perror("shmget error");
    exit(-1);
}
printf("%d\n",memid);

if((nptr2=(char*)shmat(memid,0,0))==(char*)-1){
    perror("shmat error");
    exit(-1);
}

//Estatistiken memoria sortu eta atzitu
if ((memid2=shmget(0x12345L,sizeof(stats),0600|IPC_CREAT))<0){
    perror("shmget error");
    exit(-1);
}
printf("%d\n",memid);

if((nptr=(struct estadistikak*)shmat(memid,0,0))==(struct estadistikak*)-1){
    perror("shmat error");
    exit(-1);
}

The part in which the problem happends

Notice that nptr and nptr2 are two different memory pointers that had no relation between them.

printf("Sartu nahi duzun mezua:\n");
fflush(stdout);
__fpurge(stdin);
fgets(mezua,50,stdin);

printf("Before: %d\n",nptr->erabiltzaile);
strcpy(nptr2,mezua);
printf("After: %d\n",nptr->erabiltzaile);
strcpy(mezua2,nptr2);
printf("Mi mensaje: %s\n",mezua2);

The output with printfs

Sartu nahi duzun mezua:
asdf
Before: 1
After: 1717859169
Mi mensaje: asdf

Thanks for your time and have a nice code!

Was it helpful?

Solution

You attach to the same memid twice:

if ((memid=shmget(0x1234L,sizeof(mezua),0600|IPC_CREAT))<0){
    perror("shmget error");
    exit(-1);
}

if((nptr2=(char*)shmat(memid,0,0))==(char*)-1){
    perror("shmat error");
    exit(-1);
}

//Estatistiken memoria sortu eta atzitu
if ((memid2=shmget(0x12345L,sizeof(stats),0600|IPC_CREAT))<0){
    perror("shmget error");
    exit(-1);
}
printf("%d\n",memid);

if((nptr=(struct estadistikak*)shmat(memid,0,0))==(struct estadistikak*)-1){
    perror("shmat error");
    exit(-1);
}

The second should be:

if((nptr=(struct estadistikak*)shmat(memid2,0,0))==(struct estadistikak*)-1){
    perror("shmat error");
    exit(-1);
}

Having said that, it seems cock-eyed to have nptr2 attached to memid and nptr attached to memid2. I'd go with consistent suffixes:

nptr1    memid1
nptr2    memid2

Hence:

if ((memid1 = shmget(0x1234L, sizeof(mezua), 0600|IPC_CREAT)) < 0)
    err_exit("shmget 1");

if ((nptr1 = (char*)shmat(memid1, 0, 0)) == (char*)-1)
    err_exit("shmat 1");

if ((memid2 = shmget(0x12345L, sizeof(stats), 0600|IPC_CREAT)) < 0)
    err_exit("shmget 2");

if ((nptr2 = (struct estadistikak*)shmat(memid2, 0, 0)) == (struct estadistikak*)-1)
    err_exit("shmat 2");

And err_exit() might be as simple as:

void err_exit(const char *msg)
{
    perror(msg);
    exit(-1);
}

Though I usually use a more complex variable-arguments, printf-like function.

OTHER TIPS

There would seem to be three explanations for this:

  1. Your implementation of strcpy is broken.
  2. The pointers nptr and nptr2 do not refer to distinct locations in memory.
  3. The pointer nptr2 refers to a block of length less than 50, and you are therefore overwriting that block.

I personally think that the first option is unlikely. So, concentrate on the others. Check the addresses of nptr and nptr2. Check that they are not overlapping and that nptr2 refers to a block of length at least 50.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top