从注释继续,没有必要分配指针到struct client,然后为每个struct分配。简单地分配/重新分配 struct 数组 会更有意义。您还必须确保:
/* some socket code populates ip_address, port and timestamp */
实际上是为char *ip_address; 分配存储空间,因为它只是一个指针,在使用之前必须指向有效存储空间。
您的分配/重新分配方案也有点乱。在尝试使用阵列中的额外存储之前,您需要检查是否需要重新分配。此外,您总是realloc 指向一个临时指针,以避免丢失指向您的数据的指针是(以及何时)realloc 失败返回NULL。如果您使用原始指针重新分配,例如clients = realloc (clients, ...) 和 realloc 返回 NULL 你用 NULL 覆盖你的指针地址丢失你的指针并造成内存泄漏。
改变顺序并实现临时指针的使用,您可以执行以下操作:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NSTRUCT 8 /* initial number of struct to allocate */
struct client {
char *ip_address; /* must be allocated separately */
int port;
struct timeval last_seen;
};
int main (void) {
size_t n_clients = 0, /* number of clients filled */
n_alloced = NSTRUCT; /* number of clients allocated */
struct client *clients = malloc (n_alloced * sizeof *clients);
if (!clients) { /* validate every allocation */
perror ("malloc-clients");
return 1;
}
for (uint32_t iter = 0; ; iter++) {
if (n_clients == n_alloced) { /* check if realloc required */
/* always realloc with a temporary pointer, or risk data loss */
void *tmp = realloc (clients, 2 * n_alloced * sizeof *clients);
if (!tmp) { /* validate reallocation */
perror ("realloc-clients");
break; /* don't exit, original clients still valid */
}
clients = tmp; /* assign reallocated block to clients */
n_alloced *= 2; /* update allocated number of struct */
}
struct client client = {client_ip_address, client_port, timestamp};
/* some socket code populates ip_address, port and timestamp */
if (/* client filled correctly */) {
memcpy (&clients[n_clients], &client, sizeof client);
n_clients++;
}
}
}
(注意: client.ip_address 的存储必须是已分配类型,此外,由于 client 只是一个结构,clients[n_clients] = client; 就足够了 - 并且 client 必须完全填充没有其他成员或子成员需要额外分配成员的深拷贝。)
不要忘记free()在不再需要时分配的内存。
编辑 - 一些套接字代码没有分配给 client.ip_address
由于您的struct client 包含一个指向字符的指针 作为.ip_address 成员,如果您的"some socket code" 没有为.ip_address 分配存储空间,您将不得不单独复制该成员(深拷贝)。使用具有自动存储持续时间的简单成员分配,您可以将client.ip_address分别分配和复制到clients[n_clients].ip_address,如下所示:
/* some socket code populates ip_address, port but doesn't
* allocate storage for client.ip_address -- you must copy.
*/
if (/* client filled correctly */) {
/* assignment is sufficient for non-allocated members */
clients[n_clients] = client;
size_t len = strlen (client.ip_address);
clients[n_clients].ip_address = malloc (len + 1);
if (!clients[n_clients].ip_address) {
perror ("malloc-clients[n_clients].ip_address");
break;
}
memcpy (clients[n_clients].ip_address, client.ip_address,
len + 1);
n_clients++;
}
(这也意味着在释放数组之前,您必须分别 free() 每个 .ip_address 成员)
如果您的编译器提供strdup(),您可以将.ip_address 的副本简化为:
clients[n_clients].ip_address = strdup (client.ip_address);
/* strdup allocates -- so you must validate */
if (!clients[n_clients].ip_address) {
perror ("strdup-clients[n_clients].ip_address");
break;
}