Reputation: 11
I have some legacy unmanaged code (unsafe, intptr) which uses VirtualAlloc method from kernel32.dll many times in order to allocate unmanaged intptrs. This code is in a project which was upgraded from .net framework to .net 6 (core).
When I publish and run this code on linux ubuntu platform I get this exception:
An unhandled exception was thrown by the application.
2022-11-03T10:55:31.08+0200 [APP/PROC/WEB/0] OUT System.AggregateException: One or more errors occurred. (Unable to load shared library 'kernel32.dll' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: libkernel32.dll: cannot open shared object file: No such file or directory)
I assume kernel32.dll cannot be used in .net core as a cross platform dll?
I tried to use Marshal.AllocHGlobal() instead, but I am getting this exception:
attempted to read write protected memory
because some intptr sizes in application are now corrupted
Marshal.AllocHGlobal() and VirtualAlloc() does the same? I cannot use Marshal.AllocHGlobal() instead of VirtualAlloc() without changing the sizes of variables in the application?
Upvotes: 1
Views: 340
Reputation: 11
VirtualAlloc method can allocate memory with IntPtr.Zero:
VirtualAlloc(IntPtr.Zero, size, MEM_COMMIT | MEM_RESERVE | f, PAGE_READWRITE);
The problem was that Marshal.AllocHGlobal was allocating memory with garbage. From msdn: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.allochglobal?view=netframework-4.8
When AllocHGlobal calls LocalAlloc, it passes a LMEM_FIXED flag, which causes the allocated memory to be locked in place. Also, the allocated memory is not zero-filled.
Therefore writing '0' to array solved the problem:
var zeroPtr = Marshal.AllocHGlobal(size);
for (int i = 0; i < size; i++)
{
Marshal.WriteByte(zeroPtr, i, 0);
}
Upvotes: 0