【问题标题】:Could there be any difference of binary unformatted data on different platforms?不同平台上的二进制无格式数据会不会有什么不同?
【发布时间】:2017-02-28 22:29:56
【问题描述】:

我正在用两个超级老程序代码 A 和代码 B 做一个科学项目。这两个代码之间的交互是通过二进制无格式数据。数据排列为每四个字节组合成一个浮点数。这两个程序都是多年前编写的,开发人员现在在不同的机构,很难联系。由于需要紧急看结果进行防御,而且我的程序不是很好,所以我使用与开发者或modder相同的平台来编译和运行程序,以避免调试麻烦。

代码 A 主要是用 C 编写的,其余部分是用 bash 和 FORTRAN 编写的。目前尚不清楚开发人员在哪个平台上编写了此程序,但我使用的是去年毕业的学生传递的修改版本。学生在 Windows 的 64 位 Cygwin 上修改了程序,我发现这是唯一一个我可以编译和运行它而不会出错的平台。例如,如果我在 OSX、Ubuntu 或 32 位 Cygwin 上运行它,由于我的时间和编程技能有限,我会遇到超出我可以处理范围的错误。

代码 B 在 SunOS 上用 C 语言编写,依赖于 Sun 性能库。同样,我只能在我们计算机实验室的一台老式 Solaris 机器上成功编译和运行它。在其他平台上,我有大量丢失的标题,收集所有标题非常麻烦。根据文档,代码 B 使用代码 A 的输出二进制数据,格式排列方式完全相同。如果我将输出数据从代码 A 复制到代码 B 并运行它,代码 B 会抱怨数据的有效性 /* 屏幕输出:检测到负值! */.尽管如此,如果我使用其目录中提供的示例数据(开发人员用来编写和测试他的程序的数据),代码 B 的运行没有问题。

首先,如果我尝试只使用代码B的数据读取功能,创建一个简单的C项目并在我的main()函数中调用它,我发现在我的IDE中我无法重现该BUG。原代码B中的数据读取算法如下:

int i, nxyz, fildes;
char  msg[1024];
nxyz = nx * ny * nz;
if ((fildes=open(vmfile, O_RDONLY, 0664)) <= 1)
{
    perror(vmfile);
    return 1;
}
if (read(fildes, vmodel, nxyz*sizeof(float)) < 0)
{
    sprintf(msg, "Reading %s\0", vmfile);
    perror(msg);
    return 2;
}
/* checking validity codes go here */
close(fildes);

该函数正在正确读取我的二进制未格式化数据,但未正确读取开发人员的数据。这与尝试在 Solaris 上编译项目时发生的情况相反。

其次,我尝试绕过代码B的数据读取函数,编写一个新函数通过ASCII文件读取数据,并确保存储数据的数组正确返回给main()函数。进行此修改后,数据正​​确加载,但出乎意料的是,在加载数据后,程序立即停止并引发了一个分段错误,这在使用开发人员的示例数据运行时从未见过。我不确定是否应该继续处理这个新错误或放弃这个想法。

那么,二进制无格式数据在 32 位和 64 位平台、Linux 和 Windows、Solaris 和其他 Linux 机器上是否有任何区别?如果有的话,在这种紧急情况下,有什么方法可以在不修改源代码的情况下转换数据 /* 因为它必须比任何调试都快得多 */?

【问题讨论】:

    标签: c binary cygwin solaris sunos


    【解决方案1】:

    如果 Solaris 机器是 SPARC,那么除非程序仔细按照指定的顺序格式化数据,否则大于字节的数字将按照不同于 Intel CPU 使用的顺序存储,就像您在 Windows 上发现的那样机器。这称为 endianness

    浮点数也可以写成多种格式,但IEEE floating point standard 可能是这里使用的格式。如果您想了解此类数据的局限性和可能出现的错误,当然有a lot more to know about how floating point numbers are handled

    【讨论】:

      【解决方案2】:

      不同的平台很容易有不同的基础数据大小。

      已经在 32 位和 64 位之间的 cygwin 上存在数据大小差异 关于指针,long,long double。 尝试在所有不同平台之间比较类似此程序输出的内容:

      $ cat  size_of.c
      #include <stdint.h>
      #include <stdio.h>
      #include <math.h>
      
      int
      main()
      {
        printf("sizeof(char) == %d\n", sizeof(char));
        printf("sizeof(short) == %d\n", sizeof(short));
        printf("sizeof(int) == %d\n", sizeof(int));
        printf("sizeof(long) == %d\n", sizeof(long));
        printf("sizeof(long long) == %d\n", sizeof(long long));
        printf("sizeof(long long int) == %d\n", sizeof(long long int ));
        printf("sizeof(float) == %d\n", sizeof(float));
        printf("sizeof(double) == %d\n", sizeof(double));
        printf("sizeof(long double) == %d\n", sizeof(long double));
        printf("sizeof(wchar_t) == %d\n", sizeof(wchar_t));
        printf("sizeof(u_long) == %d\n", sizeof(u_long));
        printf("sizeof(ssize_t) == %d\n", sizeof(ssize_t));
        printf("sizeof(size_t) == %d\n", sizeof(size_t));
        void *p;
        printf("sizeof(*void) == %d\n", sizeof(p));
      
        return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多