简体   繁体   English

从C#应用程序调用C ++函数。 尝试读取或写入受保护的内存

[英]C++ function calling from C# application. Attempted to read or write protected memory

The problem below is ralated to my previous question 下面的问题与我之前的问题有关

Converting static link library to dynamic dll 将静态链接库转换为动态dll

My first step was to develop a dll, that was done. 我的第一步是开发一个dll,完成了。 (Thanks John Knoeller prakash. Your input was very helpful) (感谢John Knoeller prakash。您的意见很有帮助)

Now when i call the function in the dll from my c# application i get the error 现在当我从c#应用程序调用dll中的函数时,我得到了错误

"Attempted to read or write protected memory. This is often an indication that other memory is corrupt." “试图读取或写入受保护的内存。这通常表明其他内存已损坏。”

Here is the C++ definition 这是C ++定义

 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 我的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 am calling it as 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 is wrong? 怎么了?

I see a signature mismatch on the inp_len parameter. 我在inp_len参数上看到签名不匹配。 In the C++ definition you use a pointer to a short unsigned int, while in the C# method you use a ushort. 在C ++定义中,您使用指向short unsigned int的指针,而在C#方法中,您使用ushort。

对于指针,您必须使用IntPtr .net类型

@necrostaz @necrostaz

It is not necessary that we use IntPtr for pointers. 我们没有必要使用IntPtr作为指针。

Look below all of these four declarations are valid and currently i am 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 is still open 问题仍然存在

In addition to the missing "ref" on the inp_len declaration that Maurits pointed out, you need to make sure that your pointer sizes match. 除了Maurits指出的inp_len声明中缺少“ref”之外,还需要确保指针大小匹配。

If you're running on a 32-bit operating system you should be OK, but if your code runs on 64-bit too, then you need to ensure that either: 如果您在32位操作系统上运行,那么您应该没问题,但如果您的代码也运行在64位,那么您需要确保:

  • You mark your .net entry assembly as x86 (not Any CPU) 您将.net条目程序集标记为x86(不是任何CPU)
  • or 要么
  • You supply a 32-bit and 64-bit build of the C++ dll and install the correct one for the interop to call. 您提供了一个32位和64位的C ++ DLL构建版本,并为要调用的interop安装正确的版本。

I have 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. 在我的情况下,访问冲突的原因是内存是在DLL外部分配的。 As a solution I added two functions for memory allocation and deallocation to the DLL. 作为解决方案,我添加了两个用于内存分配和释放到DLL的函数。

Another solution could be a change of the .net security settings. 另一种解决方案可能是更改.net安全设置。 Some keywords are "Code Access Security Police Tool" (caspol.exe) and ".NET Framework Configuration Tool" (mscorcfg.msc). 一些关键字是“代码访问安全警察工具”(caspol.exe)和“.NET Framework配置工具”(mscorcfg.msc)。 In VS there is also a security tab in the project property dialog. 在VS中,项目属性对话框中还有一个安全选项卡。 I'm not an expert in .net security so someone else should know more details. 我不是.net安全专家,所以其他人应该知道更多细节。

The following code runs without any problems. 以下代码运行没有任何问题。 It's very similar to yours: 它与你的非常相似:

C++: 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;
}

C#: C#:

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]);
    }
}

Try it out. 试试看。 I have taken a look at the open parts of the library you are using. 我看了一下你正在使用的库的开放部分。 Here is a direct excerpt of the function lzo_decomp: 以下是lzo_decomp函数的直接摘录:

   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 serenity: "in" and "out" are not the function arguments for the input and output buffers but temporary pointers. 对于宁静:“in”和“out”不是输入和输出缓冲区的函数参数,而是临时指针。 What can you see (beside from bad formatted code)? 你能看到什么(除了格式错误的代码)? The only two buffers lzo1z_decompress is called with are "in" and "out". 调用lzo1z_decompress的唯一两个缓冲区是“in”和“out”。 And these two buffers are freed before the call. 在调用之前释放这两个缓冲区。 I'm not surprised that there is an access violation. 有一个访问冲突我并不感到惊讶。 I only can underline nobugz's advice: Contact the author. 我只能强调nobugz的建议:联系作者。

The 4th parameter need to be passed using out mode instead of ref. 需要使用out模式而不是ref传递第4个参数。 That solved the problem. 这解决了这个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C#和C ++:“试图读取或写入受保护的内存”错误 - C# & C++: “Attempted to read or write protected memory” Error 从C#调用C DLL导致尝试读取或写入受保护的内存 - Calling C DLL from C# caused Attempted to read or write protected memory C#DllImport c ++ dll错误:尝试读取或写入受保护的内存 - c# DllImport c++ dll error: Attempted to read or write protected memory C#的问题< - > C ++ DLLImport“试图读取或写入受保护的内存。” - Trouble with C#<->C++ DLLImport “Attempted to read or write protected memory.” 尝试读取或写入受保护的内存。 C ++ dll导入到C# - Attempted to read or write protected memory. C++ dll imported to C# c#访问c ++ dll时尝试读取或写入受保护的内存错误 - Attempted to read or write protected memory error while c++ dll is being accessed by c# 在c#中调用Delphi DLL“”,尝试读取或写入受保护的内存。 ”错误 - Calling Delphi DLL in c# ““Attempted to read or write protected memory. ” error C# dllimport:尝试读取或写入受保护的内存 - C# dllimport: Attempted to read or write protected memory C# - Marshal.Copy:尝试读取或写入受保护的内存 - C# - Marshal.Copy : Attempted to read or write protected memory 用于导入.dll的C#包装器,“尝试读取或写入受保护的内存” - C# wrapper for importing .dll, “Attempted to read or write protected memory”
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM