Binaries created on Windows 7 do not work on Windows Server 2012

An application created on a night machine does not work on Windows Server 2012, but works fine on other desktops.

An exception of the form "Attempted to read or write protected memory. This often indicates that another memory is damaged." rushes.

When I debug the use of remote debugging on the machine and the WindowsServer2012 build machine, I see that this exception is thrown at the place where kernel32 calls HeapSize done in the code. This is how HeapSize imported and called:

 [DllImport("kernel32")] static extern int HeapSize(int hHeap, int flags, void* block); // Returns the size of a memory block. public static int SizeOf(void* block) { int result = HeapSize(ph, 0, block); if (result == -1) throw new InvalidOperationException(); return result; } 

This is called part of the unsafe class constructor:

  public UnManagedBuffer(StringBuilder sb) { PtrStart = (byte*)Marshal.StringToHGlobalAnsi(sb.ToString()); Size = UnManagedMemory.SizeOf(PtrStart); PtrWriteNextValue = PtrStart + Size - 1; PtrReturnNextValue = PtrStart; } 

Any clues about what might be missing and how to fix it?

This is what I see in Windbg:

This is what I see in Windbg

EventLog shows:

  Log Name: Application Source: .NET Runtime Level: Error Keywords: Classic Description: Application: TestEngine.exe Framework Version: v4.0.30319 Description: The process was terminated due to an unhandled exception. Exception Info: System.AccessViolationException at Core.Utils.UnManagedMemory.HeapSize(Int32, Int32, Void*) at Core.Utils.UnManagedMemory.SizeOf(Void*) at Core.Utils.UnManagedBuffer..ctor</Event> Faulting application name: TestEngine.exe, version: 1.0.0.0, time stamp: 0x56b532bb Faulting module name: ntdll.dll, version: 6.3.9600.18185, time stamp: 0x5683f0c5 Exception code: 0xc0000005 Fault offset: 0x0000000000057306 Faulting process id: 0x2eb8 Faulting application start time: 0x01d164e45b12d7dd Faulting application path: C:\NGDLM\Lib\TestEngine.exe Faulting module path: C:\Windows\SYSTEM32\ntdll.dll Report Id: bea6eb89-d0d7-11e5-80eb-0050568cd888 Faulting package full name: Faulting package-relative application ID: 
+5
source share
1 answer

The code you wrote never worked.

HeapSize returns the size of the heap, for example, something allocated by calling HeapAlloc . The pointer provided by HeapSize must be the pointer returned by the HeapAlloc call:

lpMem [in]

Pointer to a memory block the size of which the function will receive. This is the pointer returned by the HeapAlloc or HeapReAlloc function.

You call HeapSize , but provide a pointer that can be anywhere inside this heap; or not in this heap at all:

  PtrStart = (byte*)Marshal.StringToHGlobalAnsi(sb.ToString()); Size = UnManagedMemory.SizeOf(PtrStart); PtrWriteNextValue = PtrStart + Size - 1; PtrReturnNextValue = PtrStart; 

Not only Marshal.StringToHGlobalAnsi() returns a pointer somewhere on the heap, not a pointer to the heap, you donโ€™t even know which heap the pointer is allocated from, because several heaps can be allocated in the process.

None of this matters because you seem to have a fundamental misunderstanding of the purpose of this function - you seem to be using it to get the size of the allocation made inside the heap. The memory returned by Marshal.StringToHGlobalAnsi() is not allocated by calling HeapAlloc() (because it is not a heap!), It is allocated by calling AllocHGlobal . The allocated memory must be freed by calling Marshal.FreeHGlobal() :

From the Marshal.StringToHGlobal() documentation:

Since this method allocates the unmanaged memory needed for the string, always free the memory by calling FreeHGlobal.

This Marshal method has nothing to do with HeapAlloc , HeapSize or related functions.

If you really want to know the size of the memory allocation of the pointer returned by Marshal.StringToHGlobal() , you can dig through the source of the Marshal class and find out that it uses the win32 LocalAlloc function. It so happened that LocalAlloc has a sister function, LocalSize , which can actually be used to determine the size of the selection.

However, there is no guarantee that this will work in the future, as the .Net infrastructure does not guarantee that it will continue to use LocalAlloc . If they change the internal elements of LocalSize , it may stop working.

...

All said:

I donโ€™t think that this is what you wanted to do first

Looking at your code again:

  PtrStart = (byte*)Marshal.StringToHGlobalAnsi(sb.ToString()); Size = UnManagedMemory.SizeOf(PtrStart); PtrWriteNextValue = PtrStart + Size - 1; PtrReturnNextValue = PtrStart; 

You are trying to find the length of the ansi string returned to you.

All this work of HeapSize or LocalSize completely irrelevant.

If you just want to find the length of the string "ansi", you just need to implement a silly simple string length or use any of the existing implementations there.

The following program uses Marshal.StringToHGlobal() and prints:

String: 'Hello'; Length: 5

  public static void Main( string[] args ) { IntPtr strPtr = IntPtr.Zero; string str = "Hello"; try { strPtr = Marshal.StringToHGlobalAnsi( str ); Console.Out.WriteLine( "String: '{0}'; Length: {1}", str, AnsiStrLen( strPtr ) ); } finally { if( strPtr != IntPtr.Zero ) { Marshal.FreeHGlobal( strPtr ); } } } public static int AnsiStrLen( IntPtr strPtr ) { int size = 0; while( Marshal.ReadByte( strPtr ) != 0 ) { size++; strPtr = IntPtr.Add( strPtr, 1 ); } return size; } 
+2
source

Source: https://habr.com/ru/post/1242716/


All Articles