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.