C内存映射结构数组泄漏

C内存映射结构数组泄漏,c,arrays,struct,shared-memory,C,Arrays,Struct,Shared Memory,我有两个文件,我正试图通过共享内存来保存它们。我在两个文件中使用类似的语句进行分配。在服务器文件中: 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)

我有两个文件,我正试图通过共享内存来保存它们。我在两个文件中使用类似的语句进行分配。在服务器文件中:

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);
我在以下链接中使用了该示例来动态分配共享内存:

当我在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 
...
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
更改客户端消息数组的10个元素,即最多为客户端[最大值]

从客户端,我得到:

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 
...
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

因此,当从另一个进程到达struct区域中的条目时,它们是混合的。如何防止这种情况发生?

问题是不能在一个结构中使用两次

在struct区域中使用的技巧是GCC扩展,它允许您在结构中使用可变长度数组。长度为零的数组充当一个头,然后您可以记住,您可以在末尾添加任意多的内存

// This starts at rptr->client_message and advances two indexes.
rptr->client_message[2] = ...;
问题是在rptr->client\u消息、rptr->server\u消息之后紧接着还有一个零长度数组。所以,当您写入rptr->client_消息时,您正在覆盖rptr->server_消息

让我们把事情简化一下,你就会明白为什么了

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_服务器_消息

没关系,它打印123。rptr->ptr_服务器_消息怎么样

也可以打印123!结果它们指向同一个内存

// 0x7ff5f1404144 0x7ff5f1404144
printf("%p, %p\n", rptr->ptr_client_message, rptr->ptr_server_message);

因此,一个结构中不能有两个零长度数组。

一个结构中不能有两个灵活的数组成员。基本上,rptr->ptr_客户端_消息和rptr->ptr_服务器_消息互为别名。谢谢,您有什么改进建议吗?顺便问一下,你是如何确定的,我指的是任何c引用的?:作为一种特殊情况,具有多个命名成员的结构的最后一个元素可能具有不完整的数组类型;这称为灵活数组成员。编译器没有警告您结构中有多个灵活数组吗?您是否已将警告级别提高到最大值?由于您正在使用GCC,并且这是一个GCC扩展,我建议您停止使用零大小的阵列,而是使用C99兼容[]灵活阵列成员!谢谢,这是ilja Everilä说过的话,但是为什么这个程序连续运行了很多次呢?它没有解释为什么该程序连续运行了5个点,但混合了客户1客户3和客户3的结果5@b.g.欢迎来到这个奇妙的世界!加上多进程共享内存,这会带来各种各样的计时问题。在没有看到您的代码的情况下,我无法推测可能会发生什么,但这是毫无意义的,因为您的代码已经进入了垃圾输入/垃圾输出的领域。这就像蒙着眼睛开车,突然偏离道路,想知道为什么我花了三分钟才撞车?为什么不是四个呢?还是两个?
// 0x7ff5f1404144 0x7ff5f1404144
printf("%p, %p\n", rptr->ptr_client_message, rptr->ptr_server_message);