为什么没有准确的C++反编译器?

Why is there no accurate C++ decompiler?

为什么无法创建一个与 Java 和 C# 一样准确运行的 C++ 反编译器?

因为 C++ 编译器通常不会在可执行文件中放入比它们绝对需要的信息更多的信息(尤其是如果它们在发布模式下编译而不是调试构建时),所以您需要准确反编译的信息该程序根本不存在于可执行文件中。

当然可以制作一个 C++ 编译器,它确实包含可执行文件中的所有必要信息(例如,在最简单的实现中,它可以简单地在可执行文件中包含源代码本身的副本),但是做所以会使可执行文件变得更大,而且大多数非开源 C++ 开发人员更希望其他人 not 能够反编译可执行文件,因此没有太多需求对于该功能。

有几个原因:

  1. 内联。许多 C++ 代码被内联到优化的构建中。这对任何形式的反编译器都会造成严重破坏。为了弄清楚一个函数是内联的,反编译器必须分析内联代码的细节并将它们匹配起来。 post-内联优化步骤可以使代码非常不同,具体取决于内联的位置。

  2. 模板。模板只使用#1,但它们会产生额外的问题。至少在理论上,一个在两个地方内联的函数可以编译成相同的汇编指令序列。但是对于使用不同模板参数实例化的模板代码呢?不同的实例通常必须编译成不同的指令序列。这变得更加困难,因为模板代码可以根据模板参数调用不同的函数集。这些函数本身可以内联。

  3. 编译时执行。模板元编程允许编译器实际执行代码。但是 C++11 的 constexpr 提供了一种更自然的方式来在编译时进行一些计算。显然,编译时函数调用或元函数实例化 不能 成为已编译可执行文件的一部分。只有他们的结果会是(因为这有点关键)。

  4. 缺乏全面的运行时反射。 C# 和 Java 都在其字节码中添加了大量有关原始源代码性质的信息。对象定义很容易检测到,对象名称、成员变量类型和名称等也是如此。C++ 编译成机器语言,不需要任何此类信息。由于它不是必需的,因此编译器不会生成它。甚至 ISO C++ 委员会的反射研究组也专注于 编译时 反射,这是在运行时不可用的信息。

    甚至 std::type_info 也没有提供任何东西。原因是,如果编译器没有检测到特定类型将调用 typeid,则编译器不需要为它生成 std::type_info 对象。即使是这样,给你的也只是一个对象的名称(和一个标识符)。仅此而已。