我使用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的共享库所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)