1

構造体の状態をバイナリ ファイルとして保存し、再度読み込みたいと考えています。私の構造体は次のようになります。

typedef struct
{
  uint8_t pointerLength;
  uint8_t *pointer;
  uint8_t NumBla;
  uinT16 Bla[MAX_NUM_Bla];
   ...
}
BAR_STRUCT, *BAR;

typedef struct
{
  int numBar;
  BAR bars[MAX_NUM_BAR];
}
FOO_STRUCT, *FOO;

保存は問題ありませんが、状態を復元します。ファイルからのバイト文字列がヒープ上にあり、ポインターがこの文字列の最初のアドレスを指しているポイントにいます。そして、私は次のようにします:

const void* dataPointer //points to adress in heap
unsigned char* bytePointer = (unsigned char*)dataPointer;

FOO foo = (FOO_STRUCT*)bytePointer;
bytePointer += sizeof(FOO_STRUCT);  

for (int i=0; i < MAX_NUM_BAR; i++) {
    foo->bars[i] = (BAR_STRUCT*)bytePointer;
}

最後の割り当てが機能せず、EXC_BAD_ACCESS が発生します。
バーはポインタの配列であるため、指している各要素のアドレスを修正する必要があります。それらはもはや有効ではないからです。そこで、bytesteam に保存したオブジェクトのアドレスを foo->bars[i]; に割り当ててみます。
しかし、foo->bars[i] をまったく変更できません。アクセスは機能しますが、新しいアドレスの割り当ては機能しません。
なぜだろう。

編集:
私はOSXで作業しているので、ファイルにバイトを書き込むためにNSDataを使用します:

bool saveCurrentState( FOO foo){
  NSMutableData *data = [NSMutableData data];
  [data appendBytes:templates length:sizeof(FOO_STRUCT)];
  for (int i=0; i < MAX_NUM_BAR; i++){
    [data appendBytes:&foo->bar[i] length:sizeof(INT_BAR_STRUCT)];
    if( foo->bar[i] != NULL )
      [data appendBytes:foo->bar[i]->pointer length:sizeof(uint8_t)*foo->bar[i]->length];
    ...
  }
}

構造体はライブラリで使用されているため、実際には変更できません。これには実際にはアクセスできません。なぜ期待どおりに機能しないのか、特に興味があります。ご覧のとおり、ポインター自体を含む構造体全体をコピーし、ポインターが指していた構造体をバイト文字列に追加します。これがもう少し明確になることを願っています。

構造体をセットアップするためにバイトストリームを読み取るとき、新しいアドレスで配列の値を変更する必要があるだけで、何らかの理由でそれが機能したくありません。

編集:NSDataでファイルを保存/読み取りしています:

NSData* data = [NSData dataWithContentsOfFile:@"path/to/file"];
const void* dataPointer = [data bytes];
4

2 に答える 2

2

あなたが求めているのはシリアライゼーション ライブラリのようです。プロトコル バッファtplなどを試してください(選択は正確なニーズによって異なります。ドキュメントを確認してください)。

この前の質問は、いくつかの問題をカバーするのに適切な仕事をしているようです。

于 2012-11-23T05:04:43.580 に答える
1

@Yanivが示唆するようにシリアライゼーションを使用する以外に、別のメモリ位置へのポインタが埋め込まれないようにするために、すべてをフラットメモリに格納することができます。

class Foo
{
private:
    // Prevent direct instantiation
    Foo();

    int numBar;

public:
    struct Bar
    {
        int pointerLength;
        int numBlas;
        uint16 blas[MAX_NUM_Bla];

        uint8* GetPointer()
        {
            return reinterpret_cast<uint8*>(this + 1);
        }
    };

    // Factory method
    static Foo* Create()
    {
        int totalSize = sizeof(Foo) + /* total size of all the Bars */;
        Foo* pFoo = reinterpret_cast<Foo*>(new char[totalSize]);

        ...
    }
};

Bar::pointer メンバーではなく、Bar::GetPointer メソッドが存在することに注意してください。これは、ポインターが指すものが Bar のメンバーのメモリの直後に移動するため、すべてがフラットになるためです。同様に、Foo 内のバーの配列は、Foo のメンバーのメモリの直後に配置されます。

于 2012-11-23T05:58:46.177 に答える