加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-16 06:53:51 所属栏目:百科 来源:网络整理
导读:我在使用libstdc的std :: any实现与mingw跨共享库边界时遇到了一个问题.它产生了一个std :: bad_any_cast,显然不应该(我相信). 我使用mingw-w64,gcc-7并使用-std = c 1z编译代码. 简化代码: main.cpp中: #include any#include string// prototype from lib
我在使用libstdc的std :: any实现与mingw跨共享库边界时遇到了一个问题.它产生了一个std :: bad_any_cast,显然不应该(我相信).

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

简化代码:

main.cpp中:

#include <any>
#include <string>

// prototype from lib.cpp
void 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.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读