我正在编写一个函数来检查是否在linux下使用以下代码加载.so:
#include <iostream>
#include <dlfcn.h>
#include <unistd.h>
using namespace std;
bool isLibraryLoaded(const string& libPath)
{
return (nullptr != dlopen(libPath.c_str(), RTLD_NOW | RTLD_NOLOAD));
}
int main(int argc, char** argv)
{
const string libPath = "/path/to/library.so";
cout << "loaded: " << isLibraryLoaded(libPath) << endl;
sleep(8); // first execution of lsof
// load lib
void* handle = dlopen(libPath.c_str(), RTLD_NOW);
cout << "handle: " << handle << endl;
if (nullptr != handle)
{
cout << "loaded: " << isLibraryLoaded(libPath) << endl;
}
else
{
cout << "error: " << dlerror() << endl;
}
sleep(8); // second execution of lsof
// unload lib
if (0 == dlclose(handle))
{
cout << "loaded: " << isLibraryLoaded(libPath) << endl;
}
else
{
cout << "error: " << dlerror() << endl;
}
sleep(8); // third execution of lsof
return 0;
}
程序输出:
loaded: 0
handle: 0x6420b0
loaded: 1
loaded: 1
首次执行lsof:
# lsof /path/to/library.so
(return -1)
第二次执行lsof:
# lsof /path/to/library.so
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
test 3240 me mem REG 8,33 333493040 5242954 /path/to/library.so
第三次执行lsof:
# lsof /path/to/library.so
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
test 3240 me mem REG 8,33 333493040 5242954 /path/to/library.so
程序非常简单,应该再次加载和卸载库。但事实并非如此。我很困惑,并有以下问题:
我的环境:
g++ (Ubuntu 6.4.0-17ubuntu1~16.04) 6.4.0 20180424
答案 0 :(得分:2)
此代码:
bool isLibraryLoaded(const string& libPath)
{
return (nullptr != dlopen(libPath.c_str(), RTLD_NOW | RTLD_NOLOAD));
}
是错误的,因为IFF已经加载了库(即如果函数返回true
),则句柄引用计数增加dlopen
。您需要匹配dlclose
来撤消该增量。
这是固定版本:
bool isLibraryLoaded(const string& libPath)
{
void *h = dlopen(libPath.c_str(), RTLD_NOW | RTLD_NOLOAD);
if (h != nullptr) {
dlclose(h);
return true;
}
return false;
}
使用该修复程序:
$ ./a.out
loaded: 0
handle: 0x19382a0
loaded: 1
loaded: 0