0

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!

MuGiK
  • 351
  • 4
  • 13
  • You need to allocate space for nptr2 before you strcpy mezua to it. Can't see the declaration of mezua2 anywhere. If it is a pointer, then it needs space allocation too. – cup May 03 '14 at 11:24
  • 1
    @MuGiK Why do you assume `nptr` and `nptr2` point to different locations ? Both `shmat` calls use `memid`, you're not using `memid2`. – Chnossos May 03 '14 at 11:26
  • @cup Sorry, my mistake, when editing the question I've ereased that declaration. It's equal to mezua: char mezua2[50] – MuGiK May 03 '14 at 11:26

2 Answers2

1

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.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0

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.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Typing the command ipcs in console there are created two memory segments. First key:0x00001234 shmid:458754 perms:600 bytes:50 nattch:4. Second key:0x00012345 shmid:491527 perms:600 bytes:16 nattch:0. So, the lengths are OK. I don't know how to see if the segments are overlapping. Any idea? Thanks for being so clear ;D – MuGiK May 03 '14 at 11:49
  • Solved. Chnossos was correct, in the second shmat I used memid intead of memid2. Problems happend when using copy&paste – MuGiK May 03 '14 at 11:53