我与dlfcn.h
合作,我遇到了问题。我正在实现一个加载客户端(库)的服务器(可执行文件)。
问题是客户端库有一个静态全局变量,当我多次加载同一个库时,地址似乎相同。
以下是代码示例:
客户
(client.h)
struct player {
// Few fields...
};
(client.c)
#include <stdio.h>
#include <stdlib.h>
static struct player *pl;
void initialize() {
pl = malloc(sizeof(struct player));
printf("test_initialize, struct player address : %p\n", pl); // TEST
// Some code...
}
void finalize() {
printf("struct player address %p\n", pl);
if (pl) {
free_player(pl);
printf("test_finalize\n");
}
}
请注意,我无法修改initialize()
和finalize()
程序。给予并且必须是共同的(它是学生项目)。
服务器
(server.h)
#include <stdlib.h>
struct client {
void *handle;
void (*initialize)();
void (*finalize)();
// Few fields...
};
struct server {
size_t nb_clients;
struct client **loaded_clients;
};
(server.c)
#include <dlfcn.h>
struct client* load_client(char *path){
struct client *client = malloc(sizeof(struct client));
if(!client){
return NULL;
}
client->handle = dlopen(path, RTLD_NOW); // RTLD_NOW seems to be the most appropriate. I've tested with RTLD_LAZY with no restult.
printf("handle %d\n", *(int*)client->handle); // TEST
if(!client->handle){
free_client(client);
client = NULL;
return NULL;
}
client->initialize = dlsym(client->handle, "initialize");
client->finalize = dlsym(client->handle, "finalize");
client->initialize();
// Some code...
return client;
}
int load_clients(struct server *server, char **path, int nb_players){
server->loaded_clients = malloc(nb_players * sizeof(struct client));
if(!server->loaded_clients)
return 0;
server->nb_clients = nb_players;
for(int i = 0; i < nb_players; i++){
server->loaded_clients[i] = load_client(path[i]);
server->loaded_clients[i]->player.id = i;
server->loaded_clients[i]->player.nb_players = nb_players;
}
return 1;
}
void close_server(struct server *server){
for (int i = 0; i < server->nb_clients; ++i)
server->loaded_clients[i]->finalize();
// Some code, freeing everything properly...
}
我将客户端库编译为lib/libclient.so
。
测试代码
(test.c的)
#include "../server/server.h"
#define NB_PLAYERS 3
int main(int argc, char **argv){
char *path_lib[NB_PLAYERS] = {"lib/libclient.so", "lib/libclient.so", "lib/libclient.so"};
struct server server;
if(!load_clients(&server, path_libraries, nb_players)){
return 1;
}
close_server(&server);
return 0;
}
结果是:
handle -960790528
test_initialize, struct player address : 0xaed7a0
handle -960790528
test_initialize, struct player address : 0xaedd30
handle -960790528
test_initialize, struct player address : 0xaee2c0
struct player address 0xaee2c0
test_finalize
test_finalize
struct player address (nil)
struct player address (nil)
所以似乎客户端中的变量pl被最后一个malloc覆盖,前两个pl不可访问。还有其他选择吗?