将使用位域的大型项目转换为更可移植的内容

Convert a large project using bitfields to use something more portable

本文关键字:可移植 大型项目 位域 转换      更新时间:2023-10-16

我正在从事一个大型软件项目(几百万行代码),这个项目已经拼凑了20多年。它是Fortran/C/c++的混合体,目前针对Solaris;使用Sun Studio构建的(尽管我在clang/gcc上可以编译)。

我们正在将项目转移到Linux/x86环境。我们面临的挑战之一是在整个项目中自由分布的几千个位场。

目前的想法是或多或少地按照以下思路去做:

1)无论是手动(哎呦)还是通过某种重构工具(可能是clang),更改所有位字段定义以颠倒位字段成员的顺序;例如:

 struct SomeStruct {
 #if defined( BIG_ENDIAN )
   int x1 : size1;
   int x2 : size2;
   /* ... */
 #else
   /* ... */
   int x2 : size2;
   int x1 : size1;
 #endif
 };

2)当我们发送/接收这些位域时,我们必须修改字节顺序。

从表面上看,这似乎是一个可以通过的(尽管不是完全可移植的)hack,但我对此非常怀疑:

  • 这是容易出错的(哎呀,忘记修复字节顺序;哎呀,更新了Solaris端的结构体,而不是Linux端的)
  • 虽然Sun Studio & &;到目前为止,在测试的用例中,gcc似乎以相同的方式打包结构体/位域(当在同一平台上测试时),我不会对发现有角落用例感到丝毫惊讶,并且知道这个代码库,它会碰巧我们有使用那个角落用例的代码。从历史上看,开发人员可以为所欲为(例如,当我们开始运行静态分析工具时,我们发现许多代码抛出了const和其他各种各样的问题)。如果这里涉及到/任何/角落的情况,一些更有问题的(现有的)代码可能会变得更加脆弱。

如果我们已经不得不修改那么多代码来促进这种移动,我的直觉告诉我,我们应该花时间用一些更可移植的东西来取代它们,这些东西可以序列化/反序列化,这样比特/字节顺序就可以通过API来决定,而不是语言/编译器的细微差别。

我的问题是:解决方案是否与位场保持合理?有没有更好的解决办法?(请记住,这很容易触及30,000行或更多的代码)

我的方法是:

  • 不要弄乱结构定义
  • 查找所有加载或保存(或接收或发送)数据的位置
  • 在此添加一个到定义的字节顺序的转换(为了方便,使用过去目标的字节顺序
  • )
  • 为这种转换创建依赖于硬件实现的函数,或者更好地使用htonX和ntohX例程来转换数据到网络字节序(即BigEndian)