簡體   English   中英

C內存映射結構數組泄漏

[英]C memory mapped struct array leak

我有兩個文件,我正在嘗試通過共享內存進行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-內存映射文件-共享結構中的動態數組

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個元素,即最多更改為客戶端[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

因此,當從另一個進程到達時,結構區域中的條目將混合在一起。 我該如何預防?

問題是您不能在一個結構中兩次使用零長度數組技巧

您在struct region使用的技巧是GCC擴展,可讓您在結構中具有可變長度的數組。 零長度數組充當標題,然后您可以記住,您可以根據需要在端部增加盡可能多的內存。

// This starts at rptr->client_message and advances two indexes.
rptr->client_message[2] = ...;

問題是在rptr->client_messagerptr->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);

因此,在一個結構中不能有兩個零長度的數組。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM