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。
因为 bar 是一个指针数组,所以我需要更正每个元素指向的地址。因为它们不再有效。因此,我尝试将保存在 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 中的 Bars 数组将紧跟在 Foo 成员的内存之后。

于 2012-11-23T05:58:46.177 回答