Calling a C ++ function from a C # application. Attempted to read or write protected memory

The problem below is related to my previous question.

Convert static link library to dynamic dll

My first step was to create a dll that was done. (Thanks to John Knoeller prakash. Your input was very helpful)

Now when I call a function in the dll from my C # application, I get an error

"Attempting to read or write protected memory. This often indicates damage to another memory."

Here is the C ++ definition

extern "C" DEMO2_API void Decompress(char* inp_buff, unsigned short* inp_len, char* buffer_decomp,unsigned *output_len,unsigned short* errorCode); 

My C # Converstion p / Involke

  private static extern void Decompress( byte[] inp_buff, ref ushort inp_len, byte[] buffer_decomp, ref int output_len, ref ushort errorCode ); 

And I call it below

  byte[] dst = new byte[2048]; int outlen = 2048; ushort errorCode = 0; Decompress(src, (ushort )src.Length, dst, ref outlen,ref errorCode); return dst; 

What's wrong?

+4
source share
7 answers

The 4th parameter should be passed using out mode instead of ref. This solved the problem.

0
source

I see a signature mismatch for the inp_len parameter. In a C ++ definition, you use a pointer to a short unsigned int, and in a C # method, you use ushort.

0
source

for pointers you should use the type IntPtr.net

0
source

@necrostaz

No need to use IntPtr for pointers.

Look below, all four of these ads are valid and I am currently using it.

 [DllImport("user32.dll")] public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, String lParam); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern IntPtr SendMessage(IntPtr hWnd, Int32 Msg, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern IntPtr SendMessage(IntPtr hWnd, Int32 Msg, IntPtr wParam, StringBuilder lParam); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern IntPtr SendMessage(IntPtr hWnd, Int32 Msg, IntPtr wParam, String lParam); 
Question

remains open

0
source

In addition to the missing "ref" in the inp_len declaration that Maurits indicated, you need to make sure your pointer sizes match.

If you work in a 32-bit operating system, you should be fine, but if your code works at a 64-bit level, you need to make sure that:

  • You mark your .net assembly as x86 (and not any CPU).
  • or
  • You provide a 32-bit and 64-bit C ++ dll assembly and set the correct one for interop call.
0
source

I had the same problem two years ago. In my case, the reason for the access violation was that the memory was allocated outside the DLL. As a solution, I added two functions for allocating and freeing memory in a DLL.

Another solution might be to change the .net security settings. Some keywords are: “Code Access Security Policy Tool” (caspol.exe) and “.NET Framework Configuration Tool” (mscorcfg.msc). VS also has a security tab in the project properties dialog box. I am not an .net security expert, so someone else should know more details.

0
source

The following code works without problems. It is very similar to yours:

C ++:

 extern "C" __declspec(dllexport) void TestFunction(char* inp_buff, unsigned short* inp_len, char* buffer_decomp, unsigned *output_len, unsigned short* errorCode) { //copy input buffer to output buffer int size = min(*inp_len,*output_len); for(int i=0; i<size; i++) buffer_decomp[i] = inp_buff[i]; errorCode = 0; } 

FROM#:

 using System; using System.Runtime.InteropServices; class Program { [DllImport("TEST.DLL")] public static extern void TestFunction(byte[] inp_buff, ref ushort inp_len, byte[] out_buff, ref int out_len, ref ushort errorCode); static void Main(string[] args) { //prepare input buffer byte[] inp_buff = new byte[20]; inp_buff[0] = (byte)'T'; inp_buff[1] = (byte)'E'; inp_buff[2] = (byte)'S'; inp_buff[3] = (byte)'T'; ushort inp_len = (ushort)inp_buff.Length; //prepare output buffer byte[] out_buff = new byte[20]; int out_len = out_buff.Length; ushort errorCode = 0; TestFunction(inp_buff, ref inp_len, out_buff, ref out_len, ref errorCode); //see if copying was successful for(int i=0; i<out_len; i++) Console.Out.Write(out_buff[i]); } } 

Give it a try. I looked at the open parts of the library that you are using. Here is a direct excerpt from the lzo_decomp function:

  in = lzo_malloc(IN_LEN); out = lzo_malloc(OUT_LEN); wrkmem = lzo_malloc(LZO1Z_999_MEM_COMPRESS); if (in == NULL || out == NULL || wrkmem == NULL) { printf("out of memory\n"); } in_len = IN_LEN; lzo_memset(in,0,in_len ); lzo_memset ( out, 0, OUT_LEN ); memcpy ( out, &input_buffer, inp_buff_len); lzo_free(wrkmem); lzo_free(out); lzo_free(in); r = lzo1z_decompress(out,*inp_len,in,&out_len,NULL ); 

For peace of mind: "in" and "out" are not function arguments for input and output buffers, but temporary pointers. What can you see (besides bad formatted code)? Only two lzo1z_decompress buffers are called: "in" and "out". And these two buffers are freed before the call. I am not surprised that there is a violation of access rights. I can only emphasize the advice of nobugz: Contact the author.

0
source

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


All Articles