【问题标题】:dlsym returns an invalid pointerdlsym 返回一个无效的指针
【发布时间】:2022-01-01 20:42:52
【问题描述】:

我有一个像这样的动态链接模块:

int func() {
    return 5;
}

extern int(*func_p)() = func;

还有一个加载函数指针的主函数:

#include <stdio.h>
#include <dlfcn.h>

int main() {
    void *module = dlopen("/tmp/mod/mod.so", RTLD_NOW);
    if (!module)
  {
     printf("Cannot load module: %s\n", dlerror());
     return 1;
  }

    typedef int(*func_f)();
    func_f func;

    func = dlsym(module, "func_p");
    char *error = dlerror();
    if (error)
{
   printf("Cannot find init in module: %s\n", error);
   return 1;
}

    printf("Func returns: %i\n", func());
}

我有什么办法可以完成这项工作,还是完全超出范围?

我可以手动“解析”函数指针吗?

【问题讨论】:

  • 你试过什么?由于某些原因,您在此处发布的代码无法编译。 (例如,num 没有定义。)但是如果你修复了这些错误,这或多或少是有效的。另外,您是什么意思“手动解析”函数指针?这就是dlsym 的全部意义,按名称为您解决。
  • 对不起,我在撰写帖子时对代码进行了一些修改,并遗漏了一些内容。现已修复
  • 如果你用 dlsym(module, "func") 替换 dlsym(module, "func_p") 就可以了
  • @Rillian:我不完全确定您所说的“func_p 的定义已经取消引用”是什么意思,但我认为您对 C 中的一个奇怪的极端情况感到困惑。确实func_p() 隐式取消引用func_p,因此无需编写(*func_p)()。 (但隐式取消引用是在它的使用上下文中,而不是它的定义。)但是dlsym 不会返回您查找的符号的 value。它返回它的地址。换句话说,dysym 返回的不是func_p,而是&amp;func_p。而(&amp;func_p)() 不是合法的函数调用。
  • 您的帖子没有说明您在实施此操作时遇到了什么问题。 cmets中已经指出了一些事情,但是您需要更新帖子以描述特定问题并提出特定问题。一个特定的问题可能是“dlsym 返回一个空指针”或“我尝试在返回的地址dlsym 调用一个函数,然后程序崩溃”。对于失败的情况,它应该有完整的具体代码。

标签: c pointers segmentation-fault dynamic-linking dlopen


【解决方案1】:

在 C 中,func 是一个函数,func_p 是一个指向函数的指针。当名称作为dlsym 的参数给出时,dlsym 返回命名事物的地址。因此,对于"func",它返回名为func 的函数的地址。对于"func_p",它返回名为func_p 的指针的地址。

当然,指针func_p的地址不能用来调用函数。为此,您需要指针的值。

这些都应该工作:

// Get address of function.
int (*func)() = (int (*)()) dlsym(module, "func");

// Call function.
func();
// Get address of pointer to function.
int (**p)() = dlsym(module, "func_p");

// Deference to get pointer to function, then call function.
(*p)();

后者是不必要的,除非该功能在外部不可见。只要func能被dlsym查到,前者就够了。

还要注意关于链接器和相关事物的文档,可能是dlsym,指的是符号的值,但是,对于这些类型的符号,这些值是符号所指事物的地址。也就是说,对于 C,func 是一个函数,func_p 是一个指针,但是对于链接器,func 是它在对象模块中找到的某个名称,它的“值”是它要存放的地址在内存中,同样func_p 的值就是它所在的地址。阅读此类文档时,您必须注意链接器和符号解析器执行不同的任务,并且处理名称的方式与 C 编译器不同。

【讨论】:

  • 非常感谢。第二个例子对我有用。然而,第一个没有,也正是我在原来的问题中所做的,它被 typedef 遮盖了。您能否在我将其标记为完成之前对其进行编辑
  • 我理解第二个,你得到一个指向函数指针的指针,解引用一次并调用结果函数指针。所以第一个不起作用的原因一定是因为你正在调用一个指向函数指针的指针。
  • @RillianGrant:第一个代码可以工作,除了编译器可能需要转换来进行转换。我更新了一个演员表。我知道它有效,因为我构建并执行了它。如果它不适合您,您需要提供有关遇到的问题的信息。代码没有调用指向函数指针的指针;它通过指针调用函数,这是调用函数的唯一方法。 (当您尝试按名称调用函数时,函数指示符会自动转换为指针。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-09
  • 1970-01-01
  • 2017-11-29
  • 2013-05-23
  • 2016-07-22
  • 2011-02-11
相关资源
最近更新 更多