使用C的内存映射文件中的相对指针

问题描述 投票:5回答:3

是否可以使用具有指向内存映射文件中另一个结构的指针的结构,而不是将偏移量存储为某种整数类型并计算指针?

例如给出以下结构:

typedef struct _myStruct_t {
  int number;
  struct _myStruct_t *next;
} myStruct_t;
myStruct_t* first = (myStruct_t*)mapViewHandle;
myStruct_t* next = first->next;

代替此:

typedef struct _myStruct_t {
  int number;
  int next;
} myStruct_t;
myStruct_t* first = (myStruct_t*)mappedFileHandle;
myStruct_t* next = (myStruct_t*)(mappedFileHandle+first->next);

我读过有关'__based'关键字,但这是Microsoft特定的,因此与Windows绑定。

正在寻找使用GCC编译器的工具。

c pointers memory-mapped-files
3个回答
2
投票

我很确定没有什么类似于GCC中Visual Studio中的__based指针。我唯一看到过类似内置功能的地方是在一些非常奇怪的硬件上。 Visual Studio扩展提供了围绕涉及指针的所有操作的地址转换层。

因此,听起来您正在进入自己的领土;尽管我愿意被告知其他情况。

我上次处理这样的事情是在掌上平台上,除非您锁定内存,否则它可能会四处移动。您从分配中获得了内存句柄,在使用完它之前必须先到MemHandleLock,在使用完之后必须先到MemPtrUnlock,以便该块可以被OS移动(这似乎发生在基于ARM的Palm设备上) 。

如果您坚持将指针式的值存储在内存映射的结构中,则第一个建议是将值存储在intptr_t中,该值是可以包含指针值的int大小。虽然您的偏移量不太可能超过4GB,但为了安全起见,这是值得的。

也就是说,这很容易使用模板类在C ++中实现,只是将问题标记为C会使事情变得更加混乱。


0
投票

第一个极不可能工作。

请记住,诸如struct _myStruct_t *之类的指针是指向位置在内存中]的指针。假设此结构位于内存中的地址1000:这意味着紧随其后的下一个结构可能位于地址1008,这就是存储在->next中的内容(数字不重要;重要的是它们是内存地址)。现在,您将该结构保存到文件中(或取消映射)。然后再次映射它,但是这次,它最终从地址2000开始,但是->next指针仍然是1008

您(通常)无法控制文件在内存中的映射位置,因此无法控制映射结构中元素的实际存储位置。因此,您可以only

取决于相对偏移量。

请注意,根据mappedFileHandle的声明类型,您的第二个版本可能无法正常工作。如果它是指向myStruct_t的指针,则向其添加整数n将生成一个指向内存中的地址的指针,该地址比存储空间中的n*sizeof(myStruct_t)字节高n字节。

如果您声明mappedFileHandle

myStruct_t* mappedFileHandle;

然后您可以将其下标为数组。如果将映射文件布置为myStruct_t块的序列,并且next字段按该序列内的索引引用其他块,则(假设myStruct_t* b是感兴趣的块)

mappedFileHandle[b->next].number

是序列中第number个块的b->next字段。

(这只是在C中定义数组的方式的结果:mappedFileHandle[b->next]被定义为等效于*(mappedFileHandle + b->next),这是myStruct_t类型的对象,因此可以得到number的字段。


0
投票

C ++:这是非常可行且可移植的(代码,但可能不是数据)。不久前,但是我为自相关指针类创建了一个模板。我在可能移动的内存块中有树结构。在内部,该类具有单个intptr_t,但= *。 ->运算符已重载,因此它看起来像常规指针。处理null引起了一些注意。我还使用int,short和不太有用的char进行了版本处理,这些char对于无法指向较远空间的指针(外部内存块)。

© www.soinside.com 2019 - 2024. All rights reserved.