c – std :: any跨越mingw的共享库

c – std :: any跨越mingw的共享库,第1张

概述我在使用libstdc的std :: any实现与mingw跨共享库边界时遇到了一个问题.它产生了一个std :: bad_any_cast,显然不应该(我相信). 我使用mingw-w64,gcc-7并使用-std = c 1z编译代码. 简化代码: main.cpp中: #include <any>#include <string>// prototype from lib.cppvo 我在使用libstdc的std :: any实现与mingw跨共享库边界时遇到了一个问题.它产生了一个std :: bad_any_cast,显然不应该(我相信).

我使用mingw-w64,gcc-7并使用-std = c 1z编译代码.

简化代码:

main.cpp中:

#include <any>#include <string>// prototype from lib.cppvoID do_stuff_with_any(const std::any& obj);int main(){    do_stuff_with_any(std::string{"Hello World"});}

lib.cpp:

将编译成共享库并与main.cpp中的可执行文件链接.

#include <any>#include <iostream>voID do_stuff_with_any(const std::any& obj){    std::cout << std::any_cast<const std::string&>(obj) << "\n";}

这会触发std :: bad_any_cast,尽管传递给do_stuff_with_any的任何内容都包含一个字符串.我深入研究了gcc的任何实现,它似乎使用静态内联成员函数的地址(根据存储对象的类型从模板结构中选择的管理器)的比较来检查any是否包含所请求类型的对象.
并且该函数的地址似乎在共享库边界上发生了变化.

是不是std :: any保证跨共享库边界工作?这段代码会在某处触发UB吗?或者这是gcc实现中的错误?我很确定它适用于linux,所以这只是mingw中的一个错误吗?它是否已知或应该在某处报告? (临时)解决方法的任何想法?

解决方法 虽然这是关于windows DLL如何工作的问题,而且从GCC 8.2.0开始,问题仍然存在,这可以通过将任何标头内的__any_caster函数更改为:

template<typename _Tp>voID* __any_caster(const any* __any){  if constexpr (is_copy_constructible_v<decay_t<_Tp>>){#if __cpp_rtti  if (__any->type().hash_code() == typeID(_Tp).hash_code())#else  if (__any->_M_manager == &any::_Manager<decay_t<_Tp>>::_S_manage)#endif    {      any::_Arg __arg;      __any->_M_manager(any::_Op_access,__any,&__arg);      return __arg._M_obj;    }}  return nullptr;}

或类似的东西,唯一相关的部分是包含在#if中的比较线.

为了详细说明,在exe上有一个管理器函数的副本,在dll上有一个副本,传递的对象包含exe的地址,因为它是创建它的地方,但是一旦它到达dll一侧,指针就会被比较到dll地址空间中的一个永远不会匹配,因此,应该比较类型信息hash_codes.

总结

以上是内存溢出为你收集整理的c – std :: any跨越mingw的共享库全部内容,希望文章能够帮你解决c – std :: any跨越mingw的共享库所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1225100.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-05
下一篇 2022-06-05

发表评论

登录后才能评论

评论列表(0条)

保存