No way to determine internal offset used by MemoryMappedViewAccessor - Makes SafeMemoryMappedViewHandle property unusable - by James Chaldecott

Status : 

 


5
0
Sign in
to vote
ID 537635 Comments
Status Active Workarounds
Type Bug Repros 4
Opened 3/1/2010 7:37:30 AM
Access Restriction Public

Description

MemoryMappedViewAccessor has a SafeMemoryMappedViewHandle property, which returns the ViewHandle being used internally by the MemoryMappedView, but does not have any property to return the offset being used by the MemoryMappedView.

As the MemoryMappedView is page aligning the offset requested in MemoryMappedFile.CreateViewAccessor(offset,size) it is impossible to use the SafeMemoryMappedViewHandle for anything useful without knowing the offset.

Note that what we actually want to do is use the AcquirePointer(ref byte* pointer) method to allow some fast pointer based (possibly unmanaged) code to run. We're OK with the pointer being page aligned, but it must be possible to find out what the offset from the originally requested address is.
Sign in to post a comment.
Posted by r w g on 6/12/2017 at 1:18 PM
Looks like this has been fixed for some time (.NET 4.51?) by the addition of MemoryMappedViewAccessor.PointerOffset which gives access to the previously private PointerOffset of m_view

ie -

var view = _file.CreateViewAccessor(offset, size);
byte* ptr = null;

view.SafeMemoryMappedViewHandle.AcquirePointer(ref ptr);
var buffer = new IntPtr(ptr + view.PointerOffset);

gets the correct address corresponding to the offset specified into the memory mapped file.

Posted by Max Charp on 2/26/2012 at 10:18 AM
Temporary solution:

    public unsafe static class Helper
    {
        static SYSTEM_INFO info;

        static Helper()
        {
            GetSystemInfo(ref info);
        }

        public static byte* Pointer(this MemoryMappedViewAccessor acc, int offset)
        {
            var num = offset % info.dwAllocationGranularity;
            
            byte* tmp_ptr = null;

            RuntimeHelpers.PrepareConstrainedRegions();

            acc.SafeMemoryMappedViewHandle.AcquirePointer(ref tmp_ptr);

            tmp_ptr += num;

            return tmp_ptr;
        }

        [DllImport("kernel32.dll", SetLastError = true)]
        internal static extern void GetSystemInfo(ref SYSTEM_INFO lpSystemInfo);

        internal struct SYSTEM_INFO
        {
            internal int dwOemId;
            internal int dwPageSize;
            internal IntPtr lpMinimumApplicationAddress;
            internal IntPtr lpMaximumApplicationAddress;
            internal IntPtr dwActiveProcessorMask;
            internal int dwNumberOfProcessors;
            internal int dwProcessorType;
            internal int dwAllocationGranularity;
            internal short wProcessorLevel;
            internal short wProcessorRevision;
        }
    }

Use
            MemoryMappedFile memoryFile; /...

            var offset = 100;
            var acc = memoryFile.CreateViewAccessor(offset, 16, MemoryMappedFileAccess.ReadWrite);
            var ptr = acc.Pointer(offset);
Posted by Max Charp on 2/24/2012 at 11:36 AM
        public static int* Pointer(this MemoryMappedViewAccessor acc)
        {
            var tmp_ptr = (byte*)IntPtr.Zero;

            acc.SafeMemoryMappedViewHandle.AcquirePointer(ref tmp_ptr);

            return (int*)tmp_ptr;
        }

        public Writer GetWriter()
        {
            var offset = 0;
            var acc = memoryFile.CreateViewAccessor(offset, PageSize, MemoryMappedFileAccess.ReadWrite);
            var ptr = acc.Pointer();
            
            var offset2 = 16;
            var acc2 = memoryFile.CreateViewAccessor(offset2, PageSize, MemoryMappedFileAccess.ReadWrite);
            var ptr2 = acc2.Pointer();

            *ptr = 12345;

            if (*ptr == *ptr2)
            {
                // It's always true!!!!!!!!!!!!!!!!
                System.Diagnostics.Debugger.Break();
            }

            return new Writer((byte*)ptr, PageSize, acc, storage);
        }
Posted by James Chaldecott on 9/27/2011 at 1:35 AM
Any chance of getting this fixed in .Net 4.5?
Posted by Andy Bird on 11/19/2010 at 4:41 AM
This is also an issue for us. We have a similar use case to the original description from James. As James notes, when a view accessor is created with a non-zero offse, the AcquirePointer method appears to return a pointer to a page aligned address rather than to the start of the view so for the AcquirePointer method to be of any use in this scenario, it is necessary to know the appropriate offset to apply to the pointer (which in general is a function of both the offset applied when creating the view and the page size / alignment - ie. it's not trivial to handle this in the client code).

Ideally, the AcquirePointer method would apply the offset before returning the pointer, although since this would now be a breaking change I guess this may not be possible. Although there could be a flag added to the accessor to enable this feature for new code.

Next best would be a way to retrieve a value from the accessor that provides the appropriate offset value to be applied to the pointer returned by the AcquirePointer method. This would need to take account of the offset passed when creating the view accessor and the page alignment.

At a minimum the behaviour should be clearly documented - at present there is nothing in the documentation to indicate the the pointer returned by AcquirePointer will in general not take account of the offset passed when creating the view accessor and is therefore only really usable when the view is created with a zero offset.

Has anyone found a decent workaround for this?
Posted by David Christensen1 on 8/24/2010 at 8:38 AM
The information is available in MemoryMappedViewAccessor.m_view.PointerOffset
Unfortunately m_view is private; I can see why you might want to keep that private, but having a PointerOffset on the Accessor would be most useful
Posted by James Chaldecott on 3/23/2010 at 7:27 AM
Is there any way to get progress notifications on this? RTM must be getting pretty close, and this is a serious issue for us.
Posted by Microsoft on 3/1/2010 at 10:50 PM
Thanks for your feedback. We were able to reproduce the issue you are seeing. We are routing this issue to the appropriate group within the Visual Studio Product Team for triage and resolution. These specialized experts will follow-up with your issue.
Posted by Microsoft on 3/1/2010 at 7:03 PM
Thank you for your feedback, we are currently reviewing the issue you have submitted. If this issue is urgent, please contact support directly(http://support.microsoft.com)