从堆中为数组分配地址

时间:2012-11-23 04:57:23

标签: c++ objective-c pointers struct

我想将结构的状态保存为二进制文件并再次加载它们。 我的结构看起来像这样:

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;

保存没问题,但恢复状态。 Iam在文件的字节串在堆上并且指针指向该字符串的第一个地址的位置。 我这样做:

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 因为bars是一个指针数组,我需要纠正每个元素指向的地址。因为它们不再有效。所以我尝试将我保存在bytesteam中的对象的地址分配给foo-&gt; bars [i];
但我根本无法改变foo-&gt; 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];
    ...
  }
}

我无法真正更改结构,因为它们在lib中使用,我实际上也无法访问它。我特别感兴趣的是它没有按预期工作。 如您所见,我复制整个结构,包括指针本身,并添加指针指向字节字符串的结构。希望这能给你一点澄清。

当读取字节流来设置结构时,我只需要用新地址更改数组的值,并且由于某种原因不想工作。

编辑: 我也用NSData保存/读取文件:

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

2 个答案:

答案 0 :(得分:2)

看起来你所追求的是一个序列化库。尝试protocol bufferstpl之类的内容(选择取决于您的确切需求,请查看文档)。

previous question似乎在解决一些问题上做得不错。

答案 1 :(得分: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成员的记忆之后。