c++ - 为什么这个来自Objective-C++的dynamic_cast调试成功但发布失败?

标签 c++ objective-c++

我在最新版本的 Xcode(撰写本文时为 9.4.1)中构建了一个 C++ 框架,我再次在 Xcode 中从 Objective-C++ 代码中使用它。我需要执行从一种指针类型到另一种指针类型的 dynamic_cast。但是,dynamic_cast 仅适用于调试版本,不适用于发布版本。关于 dynamic_cast 在 Objective-C++ 中的工作方式,我是否缺少或理解导致此示例失败的某些内容?

C++ 框架

TestClass.hpp

class Parent {
    public:
    // https://stackoverflow.com/a/8470002/3938401
    // must have at least 1 virtual function for RTTI
    virtual ~Parent();

    Parent() {}
};

class Child : public Parent {
public:
    // if you put the implementation for this func 
    // in the header, everything works.
    static Child* createRawPtr(); 
};

TestClass.cpp

#include "TestClass.hpp"

Parent::~Parent() {}

Child* Child::createRawPtr() {
    return new Child;
}

Objective-C++ 命令行应用

ma​​in.mm

#import <Foundation/Foundation.h>
#import <TestCastCPP/TestClass.hpp>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Parent *parentPtr = Child::createRawPtr();
        Child *child = dynamic_cast<Child*>(parentPtr);
        NSLog(@"Was the cast successful? %s", child != nullptr ? "True" : "False");
    }
    return 0;
}

在 Debug 和 Release 中,我希望这段代码打印“True”。然而,实际上,Release 模式打印“False”。作为冒烟测试,位于 this SO postdynamic_cast工作得很好。

有趣的是,同样类型的代码在 C++ 命令行应用程序中工作,同样在 Xcode 中。我曾尝试在 Release模式下禁用优化器,但这似乎无法解决问题。

我有一个示例项目 up on GitHub here .记得在Release里编译一下看看我问题的原因。我已经包含了用于 Objective-C++ 的 TestCast 方案,以及用于直接 C++ 的 TestCastCPP 方案。

最佳答案

很难知道编译器的具体细节,因为编译器如何执行 RTTI 具有一定的灵 active (即,规范没有详细说明)。

在这种情况下,由于 Child 类没有定义任何虚函数,我怀疑编译器为 Child 类的每个翻译单元发出了 RTTI。

当链接框架和链接可执行文件时,每个都有自己的子 RTTI 信息,因为每个翻译单元都会发出自己的 RTTI。

我怀疑其中一个的父链接与另一个的父链接不匹配,因此它们没有相同的父指针,并且动态加载器没有“修复”这些东西。 (dynamic_cast<Child*> 基本上遍历父指针链,直到它通过指针值而不是 RTTI 值找到匹配项。)

如果你看过 nm -g TestCast | c++filt在应用程序和框架的转储中,您可以看到 RTTI block 。拆解它们,我认为 Child RTTI 在这两种情况下都已经解析为它们自己的 Parent RTTI。

为什么它适用于 DEBUG 而不是 RELEASE?发布优化之一可能是根据使用情况去除外部链接符号的死代码。因此 DEBUG 的动态加载器 (dyld) 能够解析符号,但 RELEASE 构建一个或多个符号已经在内部解析。

可能有一种方法可以指示应该保留和导出 RTTI 的“未使用”符号,这将因编译器/链接器而异。但这比提供避免该问题的显式“第一个虚拟函数”(例如虚拟 Child 析构函数)更麻烦。

关于c++ - 为什么这个来自Objective-C++的dynamic_cast调试成功但发布失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50929670/

相关文章:

objective-c - 从 objective-c 调用 objective-c ++ 方法

objective-c - 如何将 std::string 转换为 NSString?

c++ - C++ 中嵌套 for 循环的一行代码

c++ - 如何从 std::string 获取可写的 C 缓冲区?

c++ - LLVM 最大的好处是什么?

c++ - 如何在 Xcode 中检测带有宏的 C++ 编译器?

iphone - 什么是线性 PCM 值

c++ - 如何以编程方式启用/禁用 Windows 功能

c++ - 仅读取文本文件中的字母

objective-c - Objective-C++ 中的析构函数