Strcpy函数改变不相关的共享内存数据

时间:2014-05-03 10:50:55

标签: c shared-memory strcpy

我是一名学生正在研究一个实现两个共享内存段的简单C程序。问题是,当我使用strcpy函数和指向第二个内存段的指针nptr2时,会更改名为nptr的第一个内存段的值。

我一直在阅读另一个已经解决的问题,这些问题在字符串的末尾加上空值,因为正在复制的字符串没有空终止字符。但我希望这不是我的情况,因为我正在使用fgets。我已经向您展示了我已添加到我的代码中的一些printf的输出,以便更轻松地查看正在发生的事情。

用于nptr的结构

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

内存段声明和附件

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);
}

问题发生的部分

请注意,nptr和nptr2是两个不同的内存指针,它们之间没有关系。

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);

printfs

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

感谢您的时间,并有一个很好的代码!

2 个答案:

答案 0 :(得分:1)

您附加到同一memid两次:

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);
}

第二个应该是:

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

话说回来,nptr2附加memidnptr memid2。我会使用一致的后缀:

nptr1    memid1
nptr2    memid2

因此:

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");

err_exit()可能就像:

一样简单
void err_exit(const char *msg)
{
    perror(msg);
    exit(-1);
}

虽然我通常使用更复杂的变量参数,printf - 就像函数一样。

答案 1 :(得分:0)

对此似乎有三种解释:

  1. strcpy的实施已被破坏。
  2. 指针nptrnptr2不会引用内存中的不同位置。
  3. 指针nptr2指的是长度小于50的块,因此您将覆盖该块。
  4. 我个人认为第一种选择不太可能。所以,要专注于其他人。检查nptrnptr2的地址。检查它们是否重叠,nptr2是指长度至少为50的块。