I have a file on which I use memory mapping to create huge array (which may not fit in physical memory). There are two areas mapped on memory - array count (4 bytes) and some window which is moving on file to get access to different elements of array.
Everything works fine, unless one problem. After some multiple operations with array count (sometimes millions of operations) - I get system message "Access denied" when I am trying to read or write this count by its memory address which never changes since its creation.
It looks like this mapped page expires in some way...
type
// view info
TViewInfo = record
ptr: pointer; // pointer to fist byte in view
offset: longword; // offset of our data inside the view
addr: PPointer; // pointer to variable pointer (ptr + offset)
end;
TSizeRec = packed record
case integer of
0: (full: int64);
1: (lo, hi: longword);
end;
function TFileMappedArray.CreateView(offset: int64; size: longword; var p: pointer): TViewInfo;
var
offs: TSizeRec;
fsize: int64;
begin
p := nil;
result.addr := @p;
// view must start on the mem_granularity*N offset
// so we need to adjust our numbers
result.offset := offset mod fMemGranularity;
offs.full := (offset div fMemGranularity)*fMemGranularity;
size := size + result.offset;
fsize := int64(fMaxNumOfItems)*fItemSize + sizeof(longword);
if (offs.full fsize) then
size := fsize - offs.full;
result.ptr := MapViewOfFile(fMappingHandle, FILE_MAP_WRITE, offs.hi, offs.lo, size);
p := pointer(longword(result.ptr) + result.offset);
end;
var
fNumberOfItems: PLongword; // our counter
fNumberView: TViewInfo; // our view
// create view of first 4 bytes in file
fNumberView := CreateView(0, 4, pointer(fNumberOfItems));
// get count
array count := fNuberOfItems^;
// set count
fNumberOfItems^ := new count;
get or set count produces error sometimes, randomly and very rarely
There was mistake in releasing file handle after creating memory mapping. No expiration over time. But you should keep file handle as long as memory mapping exists.