gpt4 book ai didi

c++ - clang 编译的程序在 std::any_cast 期间抛出 std::bad_any_cast

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:59:18 24 4
gpt4 key购买 nike

我正在开发一个使用 std::any 的应用程序.

最近我发现,当我用 clang 编译它时,我得到了 bad_any_cast std::any_cast 之一的异常

我确定我正在转换为正确的类型。我添加了一些 typeid(T).name() 的转储至 cout确保插入 std::any 的类型没有区别并输入我正在尝试转换到的内容。

我试图编写简单的程序来演示它,但我无法重现它。

值得一提的是:我正在传递一包 std::any (每个内部包含不同的类型)并且只有一个有问题(它是 std::map<ENUM, int> )。

当我切换到 boost::any 时问题消失了(或者如果我使用 gcc 构建我的应用程序)。

我已经深入了解 std::any_cast实现失败:

  template<typename _Tp>
void* __any_caster(const any* __any)
{
if constexpr (is_copy_constructible_v<decay_t<_Tp>>)
{
if (__any->_M_manager == &any::_Manager<decay_t<_Tp>>::_S_manage)
{
any::_Arg __arg;
__any->_M_manager(any::_Op_access, __any, &__arg);
return __arg._M_obj;
}
}
return nullptr;
}

第二个 if 语句 (__any->_M_manager == &any::_Manager<decay_t<_Tp>>::_S_manage)不通过。

在我看来有几个 any::_Manager<decay_t<_Tp>>::_S_manage 的实例对于相同的 _Tp (可能是由于我的应用程序由几个模块组成)但我无法在更简单的示例中重现它。

你们有什么建议或提示我该如何处理吗?

编辑

受评论和答案的启发,我创建了一个示例,其中我弄乱了默认可见性(这也是我在我的应用程序中所做的事情),这似乎是问题的根源。

文件:

lib.cpp

#include <any>
#include <map>

enum class D
{
a,
b,
c,
d,
e,
};

int read(const std::any& a)
{
auto map = std::any_cast<std::map<D, int>>(a);
return map.begin()->second;
}

std::any create()
{
std::map<D, int> b = { {D::c, 5} };

std::any a(b);

return a;
}

lib2.cpp

#include <any>
#include <map>

std::any create();
int read(const std::any& a);

__attribute__ ((visibility("default"))) std::any build_bar2()
{
return create();
}

__attribute__ ((visibility("default"))) int read_foo2(const std::any& a)
{
return read(a);
}

lib3.cpp

#include <any>
#include <map>

int read(const std::any &);
std::any create();

__attribute__ ((visibility("default"))) int read_foo3(const std::any& a)
{
return read(a);
}

__attribute__ ((visibility("default"))) std::any build_bar3()
{
return create();
}

main.cpp

#include <any>

int read_foo2(const std::any& a);
std::any build_bar2();

int read_foo3(const std::any& a);
std::any build_bar3();


int main()
{
const std::any& a = build_bar3();
int av = read_foo2(a);

const std::any& b = build_bar2();
int bv = read_foo3(a);

return av == bv? 1: 0;
}

生成文件

CPP=clang++

all: main

lib.o: lib.cpp
$(CPP) -std=c++17 -fvisibility=hidden -g -O0 -fPIC -c lib.cpp -o lib.o

lib2.so: lib2.cpp lib.o
$(CPP) -std=c++17 -fvisibility=hidden -g -O0 -fPIC -shared lib2.cpp lib.o -o lib2.so

lib3.so: lib3.cpp lib.o
$(CPP) -std=c++17 -fvisibility=hidden -g -O0 -fPIC -shared lib3.cpp lib.o -o lib3.so


main: main.cpp lib3.so lib2.so
$(CPP) -std=c++17 -fvisibility=hidden -g -O0 main.cpp ./lib2.so ./lib3.so -o main

clean:
rm -f ./lib.o ./lib2.so ./lib3.so ./main

所以我有 2 个共享库,它们链接共同的静态库,负责 std::any创作和类型转换。当std::any在静态库的一个安装中创建并在另一个安装中转换我得到一个异常。

最佳答案

如果您使用的是 Linux 或 OS X 等 Unix,C++ 类型 ID 由指向类型信息的指针处理,而不是名称字符串匹配。

这意味着如果您有具有“相同”类型的共享库或静态库,但它们有自己的拷贝,则类型信息将不匹配。

这可能是也可能不是您的情况。

我相信您必须在公共(public)共享库中定义您的 any 中使用的类型,并以默认可见性声明。这应该使您的所有其他共享库都使用该拷贝而不是静态库中的隐藏拷贝。

关于c++ - clang 编译的程序在 std::any_cast 期间抛出 std::bad_any_cast,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51693605/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com