多版本动态库的变量测试
Posted 李迟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多版本动态库的变量测试相关的知识,希望对你有一定的参考价值。
前面写有文章探讨动态库环境变量传递问题,本文介绍加载不同版本动态库的函数调用情况。
问题提出
某工程使用到动态库,由于动态库存在不同版本,因此都会加载,后按需调用。为了观察“按需调用”情况,模拟实际使用情况,但作了简化,只观察某一变量的变化情况。
工程代码
设计思路
工程比较简单,分应用程序和动态库,但源码在同一目录,只是通过 Makefile 编译得到不同的目标文件。动态库的不同版本,版本号和累加的变量cnt
不同。每次编译,需将得到的动态库改名,即使用文件文件名区别不同的版本:libfoobar_0.so
、libfoobar_1.so
、libfoobar_2.so
。。
在测试函数中,创建不同线程,根据动态库文件名调用动态库。
实现代码
dl.cpp实现代码:
// 全局变量,库中没有多线程,故不加锁
static int cnt = 0; // 0表示版本0,1表示版本1,等
int GetVersion(char *version)
int ver = 2;
sprintf(version, "ver: 0.%d", ver);
return 0;
int Foo()
printf("Foo...\\n");
return 0;
int Bar()
printf("Bar...\\n");
return 0;
DL_API_t gAPI =
.name = "MyLib",
GetVersion,
Foo,
Bar,
;
///
int foo()
printf("foo22...\\n");
cnt++; // 累加1,下同
return 0;
int bar()
printf("bar22...\\n");
cnt++;
return 0;
int getcnt()
return cnt;
int init()
cnt = 100;
return 0;
int uninit()
cnt = 0;
return 0;
测试代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dlfcn.h>
#include <string.h>
#include <errno.h>
#include <thread>
#include "dl.h"
typedef int (*pfoo_t)();
pfoo_t pfoo;
void* myfunc(int a)
char filename[128] = 0;
sprintf(filename, "./libfoobar_%d.so", a);
void* handle = dlopen(filename, RTLD_LAZY); // 必须加路径
if (handle == NULL)
printf("open %s failed.\\n", filename);
return NULL;
printf("load %s handler: %p\\n", filename, handle);
char version[64] = 0;
DL_API_t* aLib = (DL_API_t*)dlsym(handle, "gAPI");
if (!aLib)
printf("dlsym failed: %s\\n", dlerror());
return NULL;
aLib->GetVersion(version);
printf("ver: %s\\n", version);
#if 0
if (aLib->Foo)
aLib->Foo();
#endif
#if 0
pfoo = (pfoo_t)dlsym(handle, "init");
if (pfoo)
pfoo();
#endif
pfoo = (pfoo_t)dlsym(handle, "foo");
if (pfoo)
pfoo();
// 复用指针
pfoo = (pfoo_t)dlsym(handle, "bar");
if (pfoo)
pfoo();
pfoo = (pfoo_t)dlsym(handle, "getcnt");
if (pfoo)
int ret = pfoo();
printf("cnt: %d\\n", ret);
dlclose(handle);
return NULL;
int main(void)
printf("so test...\\n");
void* handle = dlopen("./libfoobar.so", RTLD_LAZY); // 必须加路径
if (handle == NULL)
printf("open failed.\\n");
//return -1;
printf("in main handler: %p\\n", handle);
#define TEST_THREAD_NUM 3
int threadnum = TEST_THREAD_NUM;
std::thread threads[TEST_THREAD_NUM];
for(int i = 0; i < threadnum; i++)
threads[i] = std::thread(myfunc, i);
sleep(2); // 让不同线程错开运行
// 线程不一定占满,故要判断再join
for (auto& t: threads)
if (t.joinable())
t.join();
if (handle) dlclose(handle);
return 0;
动态库里的接口函数,在形式设计上是相同的:参数为空,返回值为空,因此在测试代码中可以复用函数指针。 对于使用dlopen
打开动态库、用dlsym
获取动态库函数接口的做法,可以不提供头文件,提前是函数封装得比较,比如提供纯粹功能接口,而不对外开放结构体。
以上两点在前面的文章没有提到,此处特意说明。
测试
测试结果:
so test...
in main handler: 0x1292060
load ./libfoobar_0.so handler: 0x7f26d4000910
ver: ver: 0.0
foo22...
bar22...
cnt: 2
load ./libfoobar_1.so handler: 0x7f26d4000910
ver: ver: 0.1
foo22...
bar22...
cnt: 3
load ./libfoobar_2.so handler: 0x7f26d4000910
ver: ver: 0.2
foo22...
bar22...
cnt: 4
根据设计思路,libfoobar_0.so
中变量初始化为0,所以版本号为0.0
,经过2个函数累加,最终值为2
。类似地,libfoobar_1.so
初始化为1,累加后的值为3,libfoobar_2.so
初始化为2,累加后的值为4。
小结
某些应用场合中,会存在“相同”动态库的不同版本,本文对此进行测试。像申请内存、释放,多线程等情况没有深入研究。从输出日志看,加载不同动态库,其返回的句柄值是一样的,但的确能体现出不同的版本,此为何原因,暂时不知道。
以上是关于多版本动态库的变量测试的主要内容,如果未能解决你的问题,请参考以下文章