记一则BUG修复:System.AccessViolationException

开发环境

win7,vs2008sp1,C++,C#

开发背景

基于MFC编写的OCX,供C#调用,其中的OCX接口如下:

void Command( void * value )      // 来自于 ocx的 .idl文件

DISP_FUNCTION_ID(CusViewCtrl, "Command", dispidCommand, Command, VT_EMPTY, VTS_I4 ) // 来自于 ocx的.cpp文件

而该Command的参数 void* 在C#中则体现为 intPtr,该 32位和64位的 ocx 被 C#2008.exe(vs2008编写) 都正常使用。

BUG现象

但客户那边用vs2022编写的c#2022.exe却报错,提示

System.AccessViolationException:"尝试读取或写入受保护的内存。这通常显示其它内存已损坏。"

很奇怪,问题就出在函数的参数类型上,经过多方面查证,C#的参数类型intPtr有以下注意事项:

1)intPtr在经 vs2008 编译后,当程序是32位为32bit,当程序64位时是64bit

2)intPtr经过 vs2022 编译后,当程序无论是32位还是64位,都认为是32bit

因此 C#2022.exe 传buffer(类似数组首地址)给 C++2008.ocx 时,作为经vs2022编译的C#2022.exe(64位程序),该地址会被截断,导致OCX会报内存错误。(32位程序能正常运行)

解决办法

是直接将 void Command( void * value ) 改成 void Command( longlong value );然后在OCX中直接将 longlong value 强转成 void* value 处理即可。

补充示例

C#.exe 里传数组给C++.ocx 方法:

C#.exe 代码:
 

private void SameFunction( )
{
    //...
    byte[] buffer = new byte[1000]; // 开辟一个数组

    SendDataToOcx( buffer ); // 将数组发送给OCX
    //...
}

private void SendDataToOcx( byte[] buffer )
{
    IntPtr pBuffer = Marshal.AllocHGlobal( buffer.Length );// 开辟非托管内存
    Marshal.Copy(buffer, 0, pBuffer, buffer.Length); // 拷贝内容
    
    axOcx.Command( pBuffer.ToInt64() ); // 将地址以64位int方式传给ocx

    Marshal.FreeHGlobal(pBuffer); // 释放非托管内存
}

C++.ocx 代码

void Ocx::Command( LONGLONG value )
{
    //...

    char* pBuffer = ( char* )value; // 强转后直接用即可

    //...
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

优视魔方

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值