c – std :: any跨越mingw的共享库
我在使用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. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |