我的标题可能不清楚,所以请允许我解释一下。我有一段这样的代码:
void* pluginFile = dlopen(fileName, RTLD_LAZY);
auto function = dlsym(pluginFile, "ExpectedFunction");
如果dlopen
返回正确的文件,则可以正常工作。我的问题是dlopen
找不到文件并返回NULL
时。当前发生的情况是发出了此呼叫:
dlsym(0x0, "ExpectedFunction");
问题是这会在我的项目中返回一个随机函数,称为ExpectedFunction
。我以为会发生这种情况,因为传递的句柄是NULL
,dlsym将返回NULL
。我无法在线找到这种用例的预期行为。
我的问题是,当您将NULL
句柄传递给dlsym
时会发生什么?它会简单地返回NULL
还是将其解释为位置0x0
的句柄?如果是后者的行为,那么我将简单地添加一个检查以确保dlopen suceeded
。如果不是,我想知道为什么如果句柄为NULL
,它会从另一个库中随机返回一个具有相同名称的函数。
我当前的用例是,我正在加载10个共享库,这些共享库都具有功能ExpectedFunction()
。但是,如果我们使用不存在的共享库的文件名调用dlopen
,它将返回NULL
。然后,dlsym
将返回指向最后加载的库的ExpectedFunction()
的指针。
答案 0 :(得分:6)
我的问题是,当将NULL句柄传递给dlsym时会发生什么?
规范说:
如果句柄未引用由dlopen()打开的有效对象,则dlsym()应返回NULL。
但是,有些保留的句柄值具有特殊的行为。如果传递此类保留句柄,则行为会有所不同。确切的值未由POSIX指定,但例如在glibc中:
# define RTLD_NEXT ((void *) -1l)
# define RTLD_DEFAULT ((void *) 0)
(void *) 0
为空,因此您不小心将RTLD_DEFAULT
传递到dlsym
中。规范说:
RTLD_DEFAULT
符号查找发生在正常的全局范围内;也就是说,使用此句柄搜索符号将找到与在程序代码中直接使用该符号相同的定义。
因此,总而言之,应该发生的情况取决于NULL是否为保留值。它保留在glibc中,并且很可能在其他实现中也保留。
在传递给dlopen
之前,应检查dlerror
是否不返回空值(或检查dlsym
是否返回空值)。
答案 1 :(得分:2)
从Ubuntu Linux上的dlfcn.h
:
/* If the first argument to `dlsym' or `dlvsym' is set to RTLD_DEFAULT
the run-time address of the symbol called NAME in the global scope
is returned. */
# define RTLD_DEFAULT ((void *) 0)
和dlsym
手册页中的
RTLD_DEFAULT
使用默认的共享库搜索顺序查找所需符号的首次出现。搜索将包括可执行文件及其依赖项中的全局符号,以及使用RTLD_GLOBAL标志动态加载的共享对象中的符号。