具有bool返回值的函数,仅设置整个寄存器的1个字节

时间:2016-04-04 13:40:01

标签: c++ visual-c++ assembly

我有以下代码片段,它是api(cdecl)的一部分。在MSVC ++中,sizeof bool是1个字节,但由于bool是实现定义的,其他编译器/作者编译的一些程序错误地定义了函数签名可能将bool视为> 1个字节并且调用下面的检查可能会在程序的一侧返回true

virtual bool isValid()
{
    return false;
    // ^ code above in asm: xor al, al
}

为了避免这种情况,我在返回之前设置了一个内联asm,xor eax, eax - 但我觉得它有点hacky,当然由于缺少内联汇编程序支持而无法在x64上运行。

使用#define bool int会起作用,但这不是我想要的,因为我的结构中有bool数据类型,并且使用它会导致损坏。

有没有像内在函数可以归零eax / rax寄存器或任何可以解决这个问题的东西?

1 个答案:

答案 0 :(得分:5)

没有什么可以做你要求的。您的问题需要一个完全不同的解决方案。

首先,任何"错误定义功能签名的代码"被打破需要修复。它永远不是在其他代码中解决它的解决方案。

接下来,您的问题不仅仅是bool正在实现定义,C ++标准使得许多内容都是实现定义的。因此,两个不同的C ++编译器很少有兼容的ABI。如果您的代码为使用其他人编译的代码提供了C ++接口,那么您可能需要生成单独编译的二进制文件,无论是以对象文件,静态库,DLL还是可执行文件的形式,对于您想要的每个不同的编译器支持。实际上,您可能需要为每个编译器的每个版本提供单独的二进制文件。

有两个C ++编译器尝试与Microsoft C ++ ABI兼容。第一个是Intel's C++ compiler,第二个是the Windows port of clang。 clang实现仍然是一项正在进行中的工作。您可能仍需要为编译代码的每个版本的Microsoft C / C ++运行时库创建单独的版本。

通过为代码提供纯C接口,可以减少需要分发的不同版本二进制文件的数量。纯C接口意味着仅使用C数据类型,仅使用声明为extern "C"的函数。虽然可以在实现中使用类,成员函数,模板,RTTI和异常等内容,但不能将其用作公共接口的一部分。一个例外是类似COM的接口,只有公共纯虚函数的类。由于Windows的C编译器都使用基本相同的C ABI并支持COM接口,因此兼容性问题不太可能成为问题。但是,bool类型(实际上是C中的_Bool类型)可能不安全,因为它是C语言的一个相对较新的类型。改为在C接口中使用int

请注意,由于C / C ++运行时差异,即使您只想分发已编译的二进制文件以供Microsoft的Visual C ++编译器使用,您仍可能需要为每个版本的编译器分发版本。这是因为每个版本都带有不同的运行时实现,并且其数据结构具有不兼容的内部布局。您不能将由一个版本的Visual C ++编译的函数中创建的STL容器传递给使用不同版本编译的函数。如果可执行文件和DLL使用不同版本的C运行时,则无法在可执行文件中为malloc分配内存,在DLL中分配free内存。

不幸的是,除非您愿意将用户限制在某个特定的编译器中,否则您可能无法轻松找到您正在寻找的问题。请注意,这是提供插件支持的程序使用的常见解决方案。 Pugins需要编译与编译可执行文件相同的编译器的相同版本。