有bool返回值的函数,只设置整个寄存器的1个字节
Posted
技术标签:
【中文标题】有bool返回值的函数,只设置整个寄存器的1个字节【英文标题】:Function with bool return value, only set 1 byte of the entire register 【发布时间】:2016-04-04 13:40:00 【问题描述】:我有以下一段代码,它是 api (cdecl) 的一部分。在 MSVC++ 中 bool 的大小为 1 字节,但由于 bool 是实现定义的,因此其他编译器编译的某些程序/作者错误地定义了函数签名可能会将 bool 视为 > 1 字节,并且调用下面的检查可能会在他们的程序一侧返回 true。
virtual bool isValid()
return false;
// ^ code above in asm: xor al, al
为了避免这种情况,我在 return 之前放了一个内联 asm xor eax, eax
- 但我觉得它有点笨拙,由于缺乏内联汇编器支持,它当然不能在 x64 上工作。
使用#define bool int
会起作用,但这不是我想要的,因为我的结构中包含 bool 数据类型,使用它会导致损坏。
有没有像内在函数这样可以将 eax/rax 寄存器归零或任何可以解决这个问题的东西?
【问题讨论】:
由不同编译器生成的两个库尝试使用实现定义的功能进行通信。你觉得这张照片有什么问题吗? 这可能会让您大吃一惊,但几乎所有基本类型的大小都是实现定义的。在这方面int
与bool
没有什么不同。
应该只有msvc++,但你知道添加插件支持会发生什么。特定程序在 x86 上使用 4 字节的签名,因此在这种情况下返回 int
应该可以工作。
如果你想在不同编译器编译的模块之间交换二进制数据,可能使用不同的 ABI,这将非常困难和痛苦,但一个好的开始是使用fixed-size integers 而不是任意大小类型。继续的一个好方法是根本不使用 C++ 功能,因为那很可能根本行不通,而是使用仅具有固定大小的 C 兼容数据类型的普通 C 接口..
如果这不是重复的,它值得一票,因为潜在的不兼容性有多深并不明显。
【参考方案1】:
没有什么可以满足您的要求。您的问题需要一个完全不同的解决方案。
首先,任何“错误定义函数签名”的代码都被破坏并需要修复。在其他代码中解决它永远不是解决方案。
接下来您的问题不仅仅是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 需要与编译可执行文件的编译器版本相同。
【讨论】:
以上是关于有bool返回值的函数,只设置整个寄存器的1个字节的主要内容,如果未能解决你的问题,请参考以下文章
linux 文件IO操作中,用read函数读取文件,有没有办法每次只读取一行,而不是读取指定的字节数?