Search code examples
c#memory-mapped-files

MemoryMappedViewStream.PointerOffset has wrong value


I'm having a little trouble understanding the MemoryMappedViewStream.PointerOffset property. In this simple unit test I would expect the PointerOffset of the stream to equal 500000 however it is 41248. The length of the stream is 10000 though, so that's correct at least. The _fakeDataPath is a file of 1 million bytes.

    [TestMethod]
    public void CheckViewHasCorrectOffset()
    {
        using (var mmf = MemoryMappedFile.CreateFromFile(_fakeDataPath))
        {
            using (var stream = mmf.CreateViewStream(500000, 10000))
            {
                Assert.AreEqual(500000, stream.PointerOffset);
            }
        }
    }

The unit test output is...

Assert.AreEqual failed. Expected:<500000>. Actual:<41248>

Solution

  • CreateViewStream() is a .NET wrapper around the MapViewOfFile() winapi function. The most relevant detail of this api is:

    The combination of the high and low offsets must specify an offset within the file mapping. They must also match the memory allocation granularity of the system. That is, the offset must be a multiple of the allocation granularity.

    The allocation granularity has been 64K forever. Or to put it in another way, the native api demands that the offset you specify must always be a multiple of 65536.

    That's pretty painful and they decided to hide that restriction in the .NET wrapper. Easily done, they just need to pass a different offset to the native function so it starts at the closest aligned multiple of 65536 that's less than 500000. And use a different internal offset so you get effectively still get 500000. So you need to fix your code like this:

      Assert.AreEqual(500000 % 65536, stream.PointerOffset);