使用版本相关数据文件的软件与 32 位系统兼容的最佳实践?

Posted

技术标签:

【中文标题】使用版本相关数据文件的软件与 32 位系统兼容的最佳实践?【英文标题】:Best practice for compatibility with 32-bit systems for softwares using version dependent data files? 【发布时间】:2021-10-30 08:17:30 【问题描述】:

在简单的情况下,当程序独立于任何外部数据库时,可以编写如下形式的东西:

#include <stdint.h>
#if UINTPTR_MAX == 0xffffffff
/* 32-bit */
typedef some_type_for_32_bit_version Type;

#elif UINTPTR_MAX == 0xffffffffffffffff
/* 64-bit */
typedef some_type_for_64_bit_version Type;
#endif

并继续使用所需的类型。

现在假设程序开始读取一些元/数据文件,一些位表示文件是为 32 位还是 64 位构建的(为 32 位构建的文件也应该在 64 位上工作,文件为 64 位构建应仅适用于 64 位)。该程序在这两种情况下的运行可能几乎相同,但有细微的差异,例如一些变量对于 32 位是 uint32_t,对于 64 位是 uint64_t。

一个糟糕的解决方案是从读取该位开始,拥有该变量的不同版本以及使用它的任何结构/联合/函数,并拥有大量不必要的 if 语句。

我想有一些加载程序读取那个字节,写入另一个文件中的一些#define,运行编译器并最终运行生成的程序——但这似乎太讨厌了,我对这个想法并不感到兴奋每次运行都不得不忍受编译时间。

有什么通用的设计吗?特定于c的东西? c++?

【问题讨论】:

您是说保存文件可能是 32 位或 64 位(没有任何标题)?您将如何在 32 位程序中处理 64 位数据?如果可以,那有什么问题? @appleapple 它可以是由软件创建的文件,用于 32 位机器(也应该在 64 位机器上工作)或为 64 位机器创建的文件(应该只工作对于 64 位),编辑了问题 解决方案称为serialization。这个想法是 64 位系统具有与两种文件格式兼容的 64 位结构。 32 位系统的结构仅与 32 位文件格式兼容。在 64 位系统上读取 32 位文件时,反序列化代码会将 32 位数据提升为 64 位。用 32 位数据填充 64 位结构后,其余代码不必关心数据来自 32 位文件。 拥有一个带有一些版本信息的文件头总是有意义的。当 64 位版本读取 32 位版本时,我会将其转换一次并将其写回 64 位版本。但无论如何,一开始就读那一点还不错,转换文件将是一个好的开始(我们经常更新文件格式,并在安装程序中添加了转换器,如果找到旧版本,它会将其转换为新的)我们将与主程序分开更新转换器 更好的解决方案是一开始就没有单独的 32 位和 64 位版本的数据文件。使用与 32 位和 64 位程序兼容的单一文件格式,例如在文件中仅存储 64 位数据。 【参考方案1】:

你需要两件事:

您只想编写一个可以根据文件中的标志在两种配置中使用的解析器。这里有帮助的概念是模板。

在 C++ 中,您可以使用模板使函数或类适用于多种类型。在 C 中没有真正好的机制,因此更重要的是保持动态部分尽可能小以避免代码重复。一个简单的模板模拟是将所有代码定义为宏,类型为参数,并为这两种类型实例化两次。

在运行时动态选择变体。在这里可以使更复杂的设置更易于管理的概念是动态调度。在那里,您将创建一个通用接口并根据类型实例化 32 位或 64 位变体。

在 C++ 中,这将是一个带有虚拟方法的接口类。在 C 中,这可以很容易地复制为包含函数指针的结构。

我假设在这种情况下,对于 32 位和 64 位版本的程序,将这些值存储在本机指针大小的整数中就足够了,但是如果它们需要保留其原始文件大小,则需要更多程序代码是动态的。

根据您的描述,我建议以下简单的方法:

// When reading the file:
bool flagIs64bit = readThatFlag();
if (currentArchIs32bit() && flagIs64bit) 
  return NotSupported;


// At the core of the parser:
uintptr_t readType(void *p) 
  if (flagIs64bit) 
    return (uintptr_t)*(uint64_t*)p;
   else 
    return (uintptr_t)*(uint32_t*)p;
  

(对设计的评论:二进制文件通常应该独立于它们所使用的体系结构。这样它们就可以与尽可能多的系统兼容。这意味着应该只使用显式宽度类型(u)intNN_t 及其可能需要转换字节序。)

【讨论】:

以上是关于使用版本相关数据文件的软件与 32 位系统兼容的最佳实践?的主要内容,如果未能解决你的问题,请参考以下文章

由于与64位版本的windows不兼容,怎么弄?

sqlserver安装程序出现与运行的windows不兼容

打开空白excel提示由于与64位版本不兼容

与64位版本的windows不兼容怎么办?

如何解决64位系统与32位软件不兼容

开发版本不兼容问题