2

アプリケーションを 32 ビットから 64 ビットに移植しています。
C++ですが、Cスタイルコーディング(レガシー品)です。値を格納するためにユニオンと構造体の組み合わせが使用されているという問題があります。ここでは、任意の基本データ型のデータを保持する「Any」というカスタム データ型が使用されます。Any の実装は次のとおりです。

typedef struct typedvalue
{
long data; // to hold all other types of 4 bytes or less
short id; // this tells what type "data" is holding
short sign; // this differentiates the double value from the rest
}typedvalue;

typedef union Any 
{
double any_any;
double any_double; // to hold double value
typedvalue any_typedvalue;
}Any;

ユニオンのサイズは 8 バイトです。彼らはユニオンを使用して、特定の時点で値が 1 つだけになるようにし、構造体を使用して型を区別しました。double、long、string、char、float、および int の値をいつでも格納できます。それがアイデアです。double 値の場合、値は any_double に格納されます。他のタイプの場合は「データ」に保存され、値のタイプは「id」に保存されます。「記号」は、値「Any」が double または別の型を保持しているかどうかを示します。any_any はコード内で自由に使用され、型に関係なくアドレス空間に値をコピーします。(ある時点で何が保持されるかわからないため、これが最大の問題です!)

その文字列またはポインタ「Any」が保持されると想定される場合、それは「data」(long 型) に格納されます。64 ビットでは、ここに問題があります。ポインタは 8 バイトです。そのため、"long" を同等の 8 バイト (long long) に変更する必要があります。しかし、そうすると共用体のサイズが 16 バイトに増加し、「any_any」を自由に使用すると問題が発生します。「any_any」の使用法が多すぎて、何を保持できるかわかりません。

私はすでにこれらの手順を試しましたが、うまくいきませんでした:
1. 構造体で「長いデータ」を「長い長いデータ」に変更しました。- これにより、データを「any_any」(8 バイト) として渡すことはできなくなります。
2. 構造体を共用体内のポインターとして宣言しました。そして、構造体内の「長いデータ」を「長い長いデータ」に変更しました。- ここで発生した問題は、構造体にメモリを割り当てる必要があるポインターであるためです。「any_any」を自由に使用すると、メモリの割り当てが難しくなります。場合によっては、メモリを上書きして値を消去することがあります。
3. 「データ」の値 (キーと値のペア) を保持する別のコレクションを作成します。- この実装はアプリケーションの中核であるため、これは機能しません。コレクションは数百万のデータに実行されます。

誰でもこれで私を助けることができますか?

4

3 に答える 3

1

元の設計が非常識であるという事実を無視して、使用できます<stdint.h>(またはすぐ<cstdint>に予測可能性を少し得るために:

struct typedvalue
{
  uint16_t id;
  uint16_t sign;
  uint32_t data;
};

union any
{
  char any_raw[8];
  double any_double
  typedvalue any_typedvalue;
};

非メンバーtypedvalueのアライメント保証がないため、密集することはまだ保証されていません。必要に応じてandのように aとタイプパンを作成するcharこともできますが、それも非常に見苦しいものです。struct Foo { char x[8]; };*(uint32_t*)(&Foo.x[0])*(uint16_t*)(&Foo.x[4])

あなたが C++0x を使用している場合、sizeof(typedvalue) == sizeof(double).

于 2011-06-15T09:05:33.170 に答える
1

「誰か助けてくれませんか」これは絶望の叫びのように聞こえますが、それは完全に理解できます。

このコードを書いた人は誰でも、将来の保証や移植性をまったく尊重していませんでした。

(これは、「しかし、私たちのプラットフォームは 32 ビットです! 64 ビットを使用することはありません!」と言う人への教訓にしましょう)。

「でもコードベースが大きすぎる」と言うのは承知していますが、製品を書き直した方よいでしょう。そして今度はちゃんとやろう!

于 2011-06-15T08:57:04.927 に答える
0

8 バイトのポインターと「タイプ」フィールドの両方を格納する必要がある場合は、少なくとも 9 バイトを使用する以外に選択肢がなく、64 ビット システムのアラインメントでは、おそらく 16 バイトにパディングされます。

データ構造は次のようになります。

typedef struct {
    union {
        void   *any_pointer;
        double  any_double;
        long    any_long;
        int     any_int;
    } any;
    char        my_type;
} any;

C++0x を使用している場合は、フィールドに厳密に型指定された列挙my_typeを使用することを検討してください。以前のバージョンでは、に必要なストレージenumは実装に依存し、1 バイト以上になる可能性がありました。

メモリを節約するために、(コンパイラ固有の) ディレクティブを使用してデータ構造の最適なパッキングを要求することができますが、その結果メモリ アクセスが不整列になり、パフォーマンスの問題が発生する可能性があります。

于 2011-06-15T13:44:26.950 に答える