【问题标题】:migration c++ code 32 bit machine to 64 bit machine将 c++ 代码从 32 位机器迁移到 64 位机器
【发布时间】:2013-07-03 12:21:09
【问题描述】:

我正在处理非常旧的代码,它正在迁移到 32 位到 64 位机器。它通常使用在 32 位机器上工作正常但在 64 位机器上出现问题的数据写入文件。当我检查文件并发现它通常包含 4 个 32 位值的除法。我的意思是,如果我们在 32 位机器中有 80 个值,那么在 64 位机器中将有 20 个值。(大多数情况下)。我查看了下面的代码,但无法理解某些功能。

  1. 为什么我们在写入文件之前调用 reverse 函数。

  2. 反向函数的目的是什么。

  3. 在写入函数中,尽管我们有任何数据类型,但我们总是写入 one_ascii 值。

我尝试了一些代码来帮助我简要解释问题。请让 我知道我是否需要提供更多信息。

class  GdsHeader
{
public:
  unsigned  short  rlen;
  char      record_type;
  char      data_type;
};

class  GdsRecord
{
public:
#ifndef SWIG
  union
    {
    short    *two_int;
    int     *four_int;
    double   *eight_real;
    char     *one_ascii;
//    void    *v;
    };
#endif
  int  length;

      GdsRecord (); // { v = 0; length = 0; }
      ~GdsRecord ()  ;//  { delete v; }
  void  len (int l, int type);
};




    class  GdsBlock
    {
      bool      valid_block ();
      int      len;

    public:

      bool      record_unred;
      int      header_ftell;
      GdsHeader  h;
      GdsRecord  r;
      int      array_size;
    //  bool      re_read;

    //          GdsBlock () { re_read = false; }
              GdsBlock () { record_unred = false; header_ftell = 0; }
      void      set (int rt, int dt, int sz)
                {TBE;
                h.record_type = rt;    h.data_type = dt;
                array_size = sz;       r.len (sz, dt);TBX;
                }
       int      read_header (FILE *);
      void      read_block (FILE *);

      void      write (FILE *);
      void      prt ();
    };



    void  GdsRecord :: len (int l, int type)
{

  switch (type)
    {
    case STREAM_Bit_array:
    case STREAM_Short:  l *= 2; break;
    case STREAM_Long:    l *= 4; break;
    case STREAM_Double:  l *= 8; break;
    }
  if (l > length)
    {
    l = ((l / 8) + 2) * 8;
    if (one_ascii) delete [] one_ascii;
    one_ascii = new char[l];
    debug2.printf("GdsRecord::len  new one_ascii  len %d   one_ascii %X\n",l, one_ascii);
    length = l;
    }

}


#ifndef sparc
        static  void  reverse (int len, char *buf)
        {
          TBE;
          char  tmp[24];
         int  i;
          for (i = 0; i < len; i++) tmp[i] = buf[i];
          for (i = 0; i < len; i++) buf[i] = tmp[ (len - 1) - i];
          TBX;
        }
        inline  void  reverse (int len, short *s)  { reverse (len, (char *) s); }
        inline  void  reverse (int len, int *s)    {  reverse (len, (char *) s); }
        inline  void  reverse (int len, double *s)  { reverse (len, (char *) s); }
        inline  void  reverse (int len, unsigned char *s)  {reverse (len, (char *) s); }
        #endif

void    GdsBlock :: write (FILE *outstr)
{
TBE;
debug.printf("GdsBlock::write %X\n",outstr);
  int  i, err;
  char  *c, tmp;
  if (h.data_type == 3)
  {
      cout<<"Begin...blk.r.four_int[0] =>"<<r.four_int[0]<<endl;
  }
  if (!this)
    error.printf_exit("GdsBlock::write error !this\n");

  if (!outstr)
    error.printf_exit ("GdsBlock::write  Error - outstr == 0\n");

  err = ferror(outstr);
  cout<< __LINE__<<"    "<<__PRETTY_FUNCTION__<<endl;
  if (err)
    { {
    char  *s = strerror (err);
    fclose (outstr);
    error.printf_exit ("GdsBlock::write  error - %s, errno %d\n", s, err);
    }
  switch(h.data_type)
    {
    case 0: /* NO DATA */
      h.rlen = 4;
  cout<< __LINE__<<"    "<<__PRETTY_FUNCTION__<<endl;
      break;
      case 1: /* BIT ARRAY */
  cout<< __LINE__<<"    "<<__PRETTY_FUNCTION__<<endl;
#ifndef sparc
       reverse (2, &r.two_int[0]);
#endif
      h.rlen = (2 * array_size) + 4;
      break;
      case 2: /* TWO BYTE SIGNED INTEGER */
  cout<< __LINE__<<"    "<<__PRETTY_FUNCTION__<<endl;
#ifndef sparc
      for (i = 0; i < array_size; i++)    reverse(2,&r.two_int[i]);
#endif
      h.rlen = (2 * array_size) + 4;
      break;
      case 3: /* FOUR BYTE SIGNED INTEGER */
  cout<< __LINE__<<"    "<<__PRETTY_FUNCTION__<<endl;
#ifndef sparc
      for(i = 0; i < array_size; i++)
      {
          cout<<r.four_int[i]<<endl;
          int *temp = &r.four_int[i];
          reverse(4,temp);
          //print_stacktrace();
          cout<<r.four_int[i]<<endl;
          //r.four_int[i] = r.four_int[i] << 2 ;
      }

#endif
      h.rlen = (4 * array_size) + 4;
      break;
      case 5: /* EIGHT BYTE REAL */
  cout<< __LINE__<<"    "<<__PRETTY_FUNCTION__<<endl;
#ifndef  FPC
        for (i = 0; i < array_size; i++)    getr ((CONV *) (r.eight_real + i));
#endif
#ifdef  FPC
        for (i = 0; i < array_size; i++)    fpc (r.eight_real + i);
#endif
      h.rlen = (8 * array_size) + 4;
      break;
      case 6: /* CHARACTER ARRAY */
  cout<< __LINE__<<"    "<<__PRETTY_FUNCTION__<<endl;
      h.rlen = array_size + 4;
      break;
    default:
      error.printf_exit("Error: bad record type %d in GdsBlock :: external\n", (int) h.data_type);
      }

  if (h.rlen % 2)
    {
    r.one_ascii[h.rlen] = 0;
    h.rlen++;
    }

  cout<< __LINE__<<"    "<<__PRETTY_FUNCTION__<<endl;

  i = h.rlen - 4;
#ifndef sparc
  c = (char *) &h.rlen;
  tmp = c[0];
  c[0] = c[1];
  c[1] = tmp;
#endif
  err = fwrite (&h, 1, sizeof (h), outstr);
  if (err != sizeof(h))
    {
    err = ferror(outstr);
    if (err)
      {
      char  *s = strerror (err);
      fclose (outstr);
      error.printf_exit ("GdsBlock::write  error - %s, errno %d\n", s, err);
      }

    fclose (outstr);
    error.printf_exit("Error: bad header fwrite in GdsBlock :: write\n");
    }
#if 1
  err = fwrite (r.one_ascii, 1, i, outstr);
  if (err != i)
    {
    err = ferror(outstr);
    if (err)
   {
      char  *s = strerror (err);
      fclose (outstr);
      error.printf_exit ("GdsBlock::write  error - %s, errno %d\n", s, err);
      }

    fclose (outstr);
    error.printf_exit("Error: bad record fwrite in GdsBlock :: write\n");
    }
#endif
debug.printf("GdsBlock::write exit\n");
  TBX;
}

【问题讨论】:

  • 您的第三个问题是特定于应用程序的,而不是 C++ 问题。您和/或编写此代码的人应该知道。
  • 我认为发布问题后,我意识到这可能是 32 位到 64 位的字节序问题。不确定,但在评论后阅读
  • 尝试构建一个最小的可编译示例,在 32 位机器上写入 80,在 64 位机器上写入 20。有了这些代码片段,人们只能猜测这些片段的作用以及您的实际问题是什么。
  • 我的猜测是假设 sizeof(short) = 2 和 sizeof(int) = 4,并且在初始化和读回这些联合时会造成一些破坏。无论如何,整数除法在 64 位上工作得很好——这是肯定的。
  • 一个问题,如果可能的话,谁能告诉我。在写入文件之前反转字节的原因可能是什么。我无法弄清楚原因

标签: c++ endianness


【解决方案1】:

reverse() 反转字节顺序,具体取决于平台。这里显示的似乎只是reverse() 的非SPARC 版本,请参阅endianness

在写入文件之前反转字节顺序(即调用reverse())的原因是为了使文件格式平台(即字节序)独立。

【讨论】:

  • 反转字节顺序不会使其与字节顺序无关。只有 8 位编码是字节序无关的。如果发生字节反转,则存在字节序。
【解决方案2】:

这是一些非常糟糕的代码。你在这里复制也犯了一些错误:你复制了两次GdsRecord,而GdsBlock::write中的i变量没有声明。

无论如何,这似乎应该做什么(而且我完全不确定它是否正确,这取决于 GdsRecord::len 的工作方式以及所有这些奇妙的未充分记录的字段的确切含义并且幻数是)以大端格式写入ints。

但是,shorts 似乎并没有以大端格式写入,这很奇怪,因为我很确定这意味着它无论如何都不会在 sparc/x86 互操作性中工作。我不确定 doubles 使用什么字节顺序,所以这部分可能会或可能不会起作用。此外,如果类型不是char,我无法得出仅部分写入数据的GdsBlock::write 的读数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-01
    • 2014-08-13
    • 1970-01-01
    • 1970-01-01
    • 2015-06-20
    • 2012-04-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多