将dlfcn.h与包含静态变量的库一起使用

时间:2017-04-25 13:11:05

标签: c dynamic-library

我与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不可访问。还有其他选择吗?

0 个答案:

没有答案