macOS XCode 16 打破了在共享库中定义的“final”类型的dynamic_cast

问题描述 投票:0回答:1

假设我们有共享库,其中包含以下非常简单的

Type.h

struct Base
{
    virtual ~Base() = default;
};

struct Derived final : Base
{
    Derived();
};

Type.cpp

#include "Type.h"

Derived::Derived() = default;

main.cpp
程序:

#include "Type.h"

int main()
{
    std::shared_ptr<Base> pr;
    pr = std::make_shared<Derived>();

    auto dyncast = dynamic_cast<Derived *>(pr.get());
    if (dyncast) {
        std::cout << "OK\n";
    } else {
        std::cout << "!!! FAIL\n";
    }
    return 0;
}

使用

-O2
标志编译:

> clang++ -dynamiclib -L. -std=gnu++20 -O2 -o libOut.dylib Type.cpp
> clang++ -o out main.cpp -L. -lOut -O2 -std=gnu++20
> ./out

由于某种原因,使用 XCode 16 程序无法

dynamic_cast
并输出失败行。

以下“修复”了该问题:

  • final
    声明中删除
    Derived
  • 内联
    Derived
    构造函数
  • virtual
    添加其他
    Derived
  • 成员函数
  • 没有
    -O2
  • 的建筑
  • 将 XCode 降级至 v.15

据我了解,这里发生了某种优化,导致

dynamic_cast
失败,但是,在我看来,这看起来像是一个错误,而且是一个巨大的错误。我是不是错过了什么?

是否有某种解决方法/编译器标志可以使此工作正常?

谢谢你。

c++ xcode macos dynamic-cast
1个回答
0
投票

问题是虚拟析构函数是在标头中隐式定义的。

这会导致每个库/可执行文件对于给定类型都有自己的虚拟表。结果,RTTI 出现问题,

dynamic_cast
失败。

我已在我的 MacOS 计算机上重现了您的问题,并在下面介绍修复后,它可以正常工作:

Type.h

#pragma once

struct Base
{
    virtual ~Base();
};

struct Derived final : Base
{
    Derived();
    ~Derived();
};

Type.cpp

#include "Type.h"

Base::~Base() = default;
Derived::Derived() = default;
Derived::~Derived() = default;

在此表格中,您将获得保证,每种类型只有一张真实表格,并且位于

libOut.dylib

的内部
© www.soinside.com 2019 - 2024. All rights reserved.