【问题标题】:dlsym() workaround return typedlsym() 解决方法返回类型
【发布时间】:2017-04-20 02:27:10
【问题描述】:

dlsym() 列表中的man page

   *(void **) (&cosine) = dlsym(handle, "cos");

作为转换 dlsym() 的返回值的解决方法。

这里*(void **) (&cosine)是什么意思?我知道cosine 是之前定义的函数指针,但我不确定为什么名称前需要一个& 符号&(没有& 的错误)。此外,我不明白为什么void * (void **) 的指针又与* 一起使用。

【问题讨论】:

  • 这假定double (*cosine)(double); 或类似的较早声明。
  • 非常常见的问题。如果数据指针和代码指针大小相同,则此“解决方案”可以完美运行。否则它会严重失败。
  • @LorinczyZsigmond 总的来说你是对的,但dlsym 专门来自 POSIX,它要求这在符合要求的实现中有效。换句话说,POSIX 只允许具有平面内存模型的平台,其中所有指针都相同。
  • @ephemient 我想我知道更好的解决方案:stackoverflow.com/a/36388869/4844822
  • @ZsigmondLőrinczy 仅仅因为它们的大小相同并不意味着您可以在它们之间投射。根据 C 标准,编译器将转换为不同类型的函数指针的数据或函数指针视为无效值是完全合法的(因为它是未定义的行为)。

标签: c++ dlsym


【解决方案1】:

让我们一次一点地打开它:

&cosine

这需要一个指向变量cosine的指针,所以这将是一个指向函数指针的指针。

(void **) &cosine

我们将指向函数指针的指针转换为指向空指针的指针。

* (void **) &cosine

我们取消引用转换后的指针,将dlsym() 的结果分配给它。

实际上,正在发生的事情只是问题的一个侧面。我们没有将dlsym() 的结果转换为正确类型的函数指针,而是假设cosinevoid *(通过间接级别)并分配给它。

【讨论】:

  • 对。 C 没有定义数据指针和函数指针之间的转换。定义 void *dlsym(const char *, int) 的 POSIX 确实暗示可以在 void * 中表示函数指针(这是标准 C 中没有的保证),但这并不能解决强制转换 @987654332 的事实@ 指向函数指针的定义不明确。这里,&cosine 是一个数据指针(指向一个函数指针),并且允许通过void * 转换一个数据指针并返回,所以这让我们处于安全的基础上。
  • @ephemient,你确定它可以解决问题吗? void*double (*)(double) 似乎不是兼容的类型,因此这将违反严格的别名规则,而不是依赖于可转换为 void* 的函数指针。违反严格别名会导致 UB,但编译器确实有机会在不正确的显式转换时发出警告/错误。在我看来,如果编译器允许你这样做而不是可能在运行时由于 UB 而中断,你最好进行强制转换和静态检查。
  • @zneak 这是POSIX documentation 中的建议,通常,C 允许通过void *char * 进行指针别名。这是 POSIX 具有标准 C 所没有的要求的领域之一。
  • @ephemient,我的理解是指针别名允许是一种方式:char*something*,然后修改*something 并通过*char 回读是合法的,但是something*char*,然后修改*char再回读*something是不行的。
  • POSIX 文档确实说,符合要求的实现必须发出警告,以从 void* 直接转换为函数指针,但在我看来,就迂腐的一致性而言,如果我没有误解严格的别名,也不是很好,但他们的解决方法可以说更糟。
猜你喜欢
  • 2018-06-19
  • 2023-01-11
  • 1970-01-01
  • 2021-05-20
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 2020-11-20
  • 1970-01-01
相关资源
最近更新 更多