c# form调用c++ dll 一直有问题 不是执行失败 就是尝试读取或写入受保护的内存。这通常指示其他内存已损坏

离水的鱼儿 2018-08-28 11:27:56
c++原型 :SoftWare_API UINT WINAPI PemToDer(char *pem,INT4 pem_len,UCHAR *cert,INT4 *cert_len);
c#调用:

[DllImport(@"D:/vs2012Space/ICCarUpdateClient/ICCarUpdateClient/bin/Debug/decodecert.dll", EntryPoint = "PemToDer", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public extern static int PemToDer(char[] pem, int pem_len, ref string cert, ref int cert_len); //其他信息: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
//public extern static int PemToDer(ref char[] pem, int pem_len, ref string cert, ref int cert_len); //返回值12
// public extern static int PemToDer( string pem, int pem_len, ref string cert, ref int cert_len); //返回值12
调用:
string SignCertPEM1 = "MIIEVzCCA8CgAwIBAgICW7swDQYJKoZIhvcNAQEFBQAwNDELMAkGA1UEBhMCY24xJTAjBgNVBAMeHHU1W1BT41y4U8x7l2zVAEMAQVvGeAFnOm1Li9UwHhcNMTgwNzI2MDAwMDAwWhcNMTgwNzI2MDAwMDAwWjAmMRUwEwYDVQQDHgxs1VuaTuOIaE66ADQxDTALBgNVBBIeBAA0ADkwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAIQvRbO9RF3cNNLngFBnzr+mjAZPFw1I6vUjfSJvaCM3fVPYQMchWmKZVzWsc6FsJojC69doKDZCig9oEajT";

string publicKeyDER = SignCertPEM1 ;// Encoding.ASCII.GetString(Encoding.ASCII.GetBytes(SignCertPEM));
int publicKeyDERLen=5000;
//pem编码转der编码
char []pem = SignCertPEM.ToCharArray();
//string pem = Encoding.ASCII.GetString(Encoding.ASCII.GetBytes(SignCertPEM));
//pem = Encoding.ASCII.GetString(Encoding.ASCII.GetBytes(pem));
// char[] pem = SignCertPEM.ToCharArray();
// StringBuilder pem=new StringBuilder(SignCertPEM);
int pemLen = pem.Length;
ret = PemToDer( pem, pemLen, ref publicKeyDER, ref publicKeyDERLen); // 其他信息: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
//ret = PemToDer( ref pem, pemLen, ref publicKeyDER, ref publicKeyDERLen); //返回值12


注意:c++为多字节字符集编码,返回值为12的的解释,pem编码有其他非法字符,是不是因为C#string 里存的是Unicode字符编码导致的?但是我怎么把C#项目设置成多字符街编码的?这个一直很疑惑,还有就是一种错误报: “System.AccessViolationException”类型的未经处理的异常在 未知模块。 中发生
其他信息: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
搞了好几天了也搞不定我也是醉了,求大佬帮忙~~~
...全文
213 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
离水的鱼儿 2018-08-30
  • 打赏
  • 举报
回复
引用 4 楼 xian_wwq 的回复:
看c api的定义
感觉pem是源数据,pem_len是源数据长度;
cert是目标数据,cert_len是目标数据长度
这句赋值语句感觉有问题
string publicKeyDER = SignCertPEM1 ;

Dllimport应该这么对应

[DllImport(@"D:/vs2012Space/ICCarUpdateClient/ICCarUpdateClient/bin/Debug/decodecert.dll", EntryPoint = "PemToDer", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public extern static int PemToDer(string pem, int pem_len, StringBuilder cert, ref int cert_len);

//调用前分配空间
StringBuilder publicKeyDER = new Stringbuilder(5000);

我还是想问一下,如果我把cert参数项 换成[]byte数组形式,不加ref也可以正常调用函数并成功返回der编码。但是作为传出参数,为什么不加ref?加了ref还是报内存异常,而我在调用pemToder这个函数之前 我声明了 byte []publicKeyDER=new byte[5000];为什么传进去之后还是报内存异常呢?ref不就是引用传递吗?string类型 引用回传的时候不是应该也是变换后的值吗?虽然string是值变幻后是新的地址空间,但是引用后回传的不就应该是变换后的值的地址吗?StringBuilder这个我能理解。
离水的鱼儿 2018-08-29
  • 打赏
  • 举报
回复
引用 1 楼 stherix 的回复:
ref string是不正确的用法
建议用StringBuilder代替

我之前就试过了,不行,报“System.AccessViolationException”类型的未经处理的异常在 未知模块。 中发生
其他信息: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。”错误~!
stherix 2018-08-29
  • 打赏
  • 举报
回复
ref string是不正确的用法
建议用StringBuilder代替
离水的鱼儿 2018-08-29
  • 打赏
  • 举报
回复
引用 4 楼 xian_wwq 的回复:
看c api的定义
感觉pem是源数据,pem_len是源数据长度;
cert是目标数据,cert_len是目标数据长度
这句赋值语句感觉有问题
string publicKeyDER = SignCertPEM1 ;

Dllimport应该这么对应

[DllImport(@"D:/vs2012Space/ICCarUpdateClient/ICCarUpdateClient/bin/Debug/decodecert.dll", EntryPoint = "PemToDer", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public extern static int PemToDer(string pem, int pem_len, StringBuilder cert, ref int cert_len);

//调用前分配空间
StringBuilder publicKeyDER = new Stringbuilder(5000);

谢谢了,我搞定了,确实没分配空间导致的。。。StringBuilder 不用ref 就可以了。谢谢了~~~感谢楼上两位
离水的鱼儿 2018-08-29
  • 打赏
  • 举报
回复
引用 4 楼 xian_wwq 的回复:
看c api的定义
感觉pem是源数据,pem_len是源数据长度;
cert是目标数据,cert_len是目标数据长度
这句赋值语句感觉有问题
string publicKeyDER = SignCertPEM1 ;

Dllimport应该这么对应

[DllImport(@"D:/vs2012Space/ICCarUpdateClient/ICCarUpdateClient/bin/Debug/decodecert.dll", EntryPoint = "PemToDer", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public extern static int PemToDer(string pem, int pem_len, StringBuilder cert, ref int cert_len);

//调用前分配空间
StringBuilder publicKeyDER = new Stringbuilder(5000);

string publicKeyDER = SignCertPEM1 ;
这句应该为 string publicKeyDER =“"; 粘的时候粘贴错了,还是不行啊....还是报那个错误,pem是传进去的pem编码,pem_len是pem编码的长度,cert是传出的der编码,cert_len是传出的der编码长度。我想问下这和字符集的编码有关吗?C我用的多字节字符,而C#默认的都是Unicode编码。。。。方便给调试调用一下吗?我把动态库给你和头文件。。。。小弟实在搞不定了。太奇怪了。。。。
xian_wwq 2018-08-29
  • 打赏
  • 举报
回复
看c api的定义
感觉pem是源数据,pem_len是源数据长度;
cert是目标数据,cert_len是目标数据长度
这句赋值语句感觉有问题
string publicKeyDER = SignCertPEM1 ;

Dllimport应该这么对应

[DllImport(@"D:/vs2012Space/ICCarUpdateClient/ICCarUpdateClient/bin/Debug/decodecert.dll", EntryPoint = "PemToDer", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public extern static int PemToDer(string pem, int pem_len, StringBuilder cert, ref int cert_len);

//调用前分配空间
StringBuilder publicKeyDER = new Stringbuilder(5000);



xian_wwq 2018-08-29
  • 打赏
  • 举报
回复
提示“尝试读取或写入受保护的内存”
大多是因为非托管代码访问到空指针或者指针越界了
凡是返回数据的char*,均需要调用者先申请空间
也就是说如果使用stringbuilder,
stringbuilder是需要根据业务内容分配足够长的空间的

110,535

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧