我有一个文件,我在该文件上使用内存映射来创建巨大的数组(可能不适合物理内存)。内存上映射了两个区域 - 数组计数(4 个字节)和一些正在文件上移动以访问数组的不同元素的窗口。
一切正常,除非一个问题。在对数组计数进行多次操作(有时是数百万次操作)之后 - 当我尝试通过其内存地址读取或写入此计数时,我收到系统消息“访问被拒绝”,该地址自创建以来从未改变。
看起来这个映射页面以某种方式过期......
类型
// 查看信息
TViewInfo = 记录
ptr:指针;// 指向视图中第一个字节的指针
偏移量:长字;// 我们的数据在视图中的偏移量
地址:PPointer;// 指向变量指针的指针 (ptr + offset)
结尾;
TSizeRec = 打包记录
案例整数
0:(完整:int64);
1:(lo,hi:长字);
结尾;
函数 TFileMappedArray.CreateView(offset: int64; size: longword; var p: 指针): TViewInfo;
变量
关闭:TSizeRec;
fsize:int64;
开始
p := 无;
结果.addr := @p;
// 视图必须从 mem_granularity*N 偏移开始
// 所以我们需要调整我们的数字
result.offset := offset mod fMemGranularity;
offs.full := (offset div fMemGranularity)*fMemGranularity;
尺寸 := 尺寸 + 结果偏移量;
fsize := int64(fMaxNumOfItems)*fItemSize + sizeof(longword);
如果(offs.full fsize)那么
尺寸:= fsize - offs.full;
result.ptr := MapViewOfFile(fMappingHandle, FILE_MAP_WRITE, offs.hi, offs.lo, size);
p := 指针(longword(result.ptr) + result.offset);
结尾;
变量
fNumberOfItems:PLongword;// 我们的计数器
fNumberView:TViewInfo;// 我们的观点
// 创建文件前 4 个字节的视图
fNumberView := CreateView(0, 4, 指针(fNumberOfItems));
// 获取计数
数组计数:= fNuberOfItems^;
// 设置计数
fNumberOfItems^ := 新计数;
get 或 set count 有时会随机产生错误,而且很少发生