共享内存不能使用指针《转载》

好象是腾讯面试的第一个问题,当时就懵了,从来没有想过这个问题,然后也没有怎么考虑就说应该可以吧。回来一想便知道这是不可以的。A进程创建共享内存,如果共享的数据里面包含了指针那么指针指向的地址是A进程地址空间的某个逻辑地址,在B进程访问该地址肯定要出错的。下面的示例代码演示了这个错误。
      A进程执行下面的代码,它往共享内存里面放的是一个结构体,其中有一个指针指向一个常量字符串。该程序运行会输出共享内存映射到它地址空间的位置。
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

char* str = "fuzhijie";

//要存储的数据
typedef struct{
        char* name;
        int age;
} people;

int main(int argc, char** argv)
{
        int shm_id, i;

        key_t key;

        char temp;

        people *p_map;

        char* file = "/home/ecy/lili";

        key = ftok(file, 0);
        
        if(key==-1)
        {
                perror("ftok error");
                return -1;
        }

        /*先用ftok创建一个key,再调用shmget,创建一块共享内存区域*/
        shm_id = shmget(key, 4096, IPC_CREAT | 0660);
        if(shm_id==-1)
        {
                perror("shmget error");
                return -1;
        }

        /*将这块共享内存区附加到自己的内存段*/
        p_map = (people*)shmat(shm_id, NULL, 0);

        if (p_map == (void *)-1)
        {
            perror("shmat error");
            return -1;
        }

        people p;
         p.name = str;
        p.age = 20;

        memcpy(p_map, &p, sizeof(people));

        printf("%p, %p/n", p_map, p_map->name);

        return 0;
}
程序输出如下:
0xb7781000, 0x80487b0
      B进程从A进程创建的共享内存中读取数据,其同样也打印出共享内存映射到它的地址空间的位置。
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

typedef struct{
        char* name;
        int age;
} people;

int main(int argc, char** argv)
{
        int shm_id,i;
        key_t key;
        people *p_map;
        char* name = "/home/ecy/lili";
        key = ftok(name,0);

        if(key == -1)
        {
            perror("ftok error");
            return -1;
        }

        shm_id = shmget(key, 4096, IPC_CREAT);
        if(shm_id == -1)
        {
            perror("shmget error");
            return -1;
        }

        p_map = (people*)shmat(shm_id,NULL,0);

        printf("%p, %p/n", p_map, p_map->name);

        printf("name = %s, age = %d/n", p_map->name, p_map->age);

        if(shmdt(p_map) == -1)
        {
            perror(" detach error ");
            return -1;
        }

        return 0;
}
程序输出如下:
0xb78d6000, 0x80487b0
name = /home/ecy/lili, age = 20
      可见共享内存在A,B进程映射的位置并不一样,在A进程中0x80487b0地址存放的是"fuzhijie"这个字符串的其实处,在B进程却不是,所以这将导致错误。A进程一部分内存情况如下:
共享内存能使用指针吗? - 绚丽也尘埃 - 处女地
       B进程0x80487b0地址存放的内容却如下:
共享内存能使用指针吗? - 绚丽也尘埃 - 处女地
       虽然没有访问到非法内存,但是数据是不对的,所以共享内存不能使用指针。我在网上偶然看到一句话说ACE里面的共享内存可以使用指针,有时间需要去考究一下。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个使用共享内存访问修改类指针的示例代码: ```c++ #include <iostream> #include <cstring> #include <cstdlib> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <unistd.h> #include <pthread.h> using namespace std; #define SHMSZ 27 class SharedData { public: SharedData() : value_(0) {} ~SharedData() {} void setValue(int value) { value_ = value; } int getValue() { return value_; } private: int value_; }; int main() { int shmid; key_t key; char *shm, *s; SharedData *sharedData; //创建共享内存 key = 5678; if ((shmid = shmget(key, SHMSZ, IPC_CREAT | 0666)) < 0) { perror("shmget"); exit(1); } //将共享内存连接到进程的地址空间 if ((shm = (char*) shmat(shmid, NULL, 0)) == (char*) -1) { perror("shmat"); exit(1); } //将共享内存强制转换为共享数据对象指针 sharedData = (SharedData*) shm; //在共享数据对象中设置初始值 sharedData->setValue(100); //创建子进程 pid_t pid = fork(); if (pid < 0) { perror("fork"); exit(1); } else if (pid == 0) { //子进程中对共享数据对象进行修改 sharedData->setValue(200); exit(0); } //等待子进程结束 wait(NULL); //输出共享数据对象的值 cout << "sharedData value = " << sharedData->getValue() << endl; //将共享内存从当前进程分离 shmdt(shm); //删除共享内存 shmctl(shmid, IPC_RMID, NULL); return 0; } ``` 以上代码中,我们使用了 `shmget()` 和 `shmat()` 系统调用来创建和连接共享内存。然后,我们将共享内存强制转换为共享数据对象指针,并在共享数据对象中设置初始值。接着,我们创建了一个子进程,在子进程中对共享数据对象进行修改。最后,我们输出共享数据对象的值,将共享内存从当前进程分离并删除共享内存

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值