我有两个文件,我通过共享内存尝试IPC。我在两个文件中使用类似语句进行分配。在服务器文件中:
int fd;
int size = MAX_LEN;
int bigSize = sizeof(struct region)+ size * sizeof(struct client_message) + size * sizeof(struct server_message);
struct region *rptr = (struct region*)malloc(bigSize);
printf("region size: %d clientMessage size: %d serverMessage size: %d and the total size: %d\n", sizeof(struct region), size * sizeof(struct client_message), size * sizeof(struct server_message), bigSize);
fd = shm_open("/myregion", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (ftruncate(fd, bigSize) == -1)
printf("error creating ftruncate\n");
rptr = mmap(NULL, sizeof(struct region),
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
我已使用以下链接上的示例动态分配共享内存: C Windows - Memory Mapped File - dynamic array within a shared struct
struct client_message {
pthread_t client_id;
int question;
};
struct server_message {
pthread_t client_id;
pid_t server_id;
int answer;
};
struct region { /* Defines "structure" of shared memory */
int len;
struct client_message ptr_client_message[0];
struct server_message ptr_server_message[0];
};
当我在while循环中分配并在此服务器文件中增加j时,
(rptr->ptr_client_message[(j)%size]).question = 30;
(rptr->ptr_server_message[(j)%size]).answer = 20;
我从客户端文件中读取它:
printf("rptr len is %d and question of client %d is: %d, answer of server is %d \n", size, k%size, (rptr->ptr_client_message[(k)%size]).question, (rptr->ptr_server_message[(k)%size]).answer);
输出是令人难以置信的: 从服务器终端我得到:
rptr len is 10 and question of client 0 is: 30, answer of server is 20
rptr len is 10 and question of client 1 is: 30, answer of server is 20
rptr len is 10 and question of client 2 is: 30, answer of server is 20
...
更改client_message数组的10个元素,即最多为client [MAX_LEN]
来自客户端我得到:
rtpr len is 10 and question of client 0 is: 30, answer of server is 20
rptr len is 10 and question of client 1 is: 30, answer of server is 30
rptr len is 10 and question of client 2 is: 30, answer of server is 20
rptr len is 10 and question of client 3 is: 30, answer of server is 30
rptr len is 10 and question of client 4 is: 30, answer of server is 20
rptr len is 10 and question of client 5 is: 30, answer of server is 30
rptr len is 10 and question of client 6 is: 30, answer of server is 20
rptr len is 10 and question of client 7 is: 30, answer of server is 20
rptr len is 10 and question of client 8 is: 30, answer of server is 20
rptr len is 10 and question of client 9 is: 30, answer of server is 20
rptr len is 10 and question of client 0 is: 30, answer of server is 20
rptr len is 10 and question of client 1 is: 30, answer of server is 30
rptr len is 10 and question of client 2 is: 30, answer of server is 20
rptr len is 10 and question of client 3 is: 30, answer of server is 30
rptr len is 10 and question of client 4 is: 30, answer of server is 20
rptr len is 10 and question of client 5 is: 30, answer of server is 30
rptr len is 10 and question of client 6 is: 30, answer of server is 20
rptr len is 10 and question of client 7 is: 30, answer of server is 20
rptr len is 10 and question of client 8 is: 30, answer of server is 20
因此,当从另一个进程到达时,结构区域中的条目是混合的。我该如何防止这种情况?
答案 0 :(得分:1)
问题是你不能在一个结构中使用zero length array trick两次。
您在struct region
中使用的技巧是一个GCC扩展,允许您在结构中使用可变长度数组。零长度数组充当标题,然后你可以记住你在最后添加了尽可能多的内存。
// This starts at rptr->client_message and advances two indexes.
rptr->client_message[2] = ...;
问题是在rptr->client_message
,rptr->server_message
之后有另一个零长度数组。因此,当您写信至rptr->client_message
时,您将覆盖rptr->server_message
。
让我们简化一下,你会明白为什么。
struct region {
int len;
char ptr_client_message[0];
char ptr_server_message[0];
};
以与您相同的方式初始化它。
size_t size = 4;
struct region *rptr = malloc(sizeof(struct region) + size + size);
现在我们看起来有两个3个字符串的位置。我们加一个。
rptr->ptr_server_message[0] = 'a';
rptr->ptr_server_message[1] = 'b';
rptr->ptr_server_message[2] = 'c';
rptr->ptr_server_message[3] = '\0';
printf("server_message: %s\n", rptr->ptr_server_message);
没关系,打印abc
。现在让我们填充rptr->ptr_server_message
。
rptr->ptr_client_message[0] = '1';
rptr->ptr_client_message[1] = '2';
rptr->ptr_client_message[2] = '3';
rptr->ptr_client_message[3] = '\0';
printf("client_message: %s\n", rptr->ptr_client_message);
没关系,打印123
。那么rptr->ptr_server_message
呢?
printf("server_message: %s\n", rptr->ptr_server_message);
也打印123
!事实证明,他们指向相同的记忆。
// 0x7ff5f1404144 0x7ff5f1404144
printf("%p, %p\n", rptr->ptr_client_message, rptr->ptr_server_message);
因此,在一个结构中不能有两个零长度数组。