C#调用C++ DLL时AES_init_ctx触发System.AccessViolationException崩溃
解决C++ DLL与C#互操作中的System.AccessViolationException错误
核心问题分析
出现System.AccessViolationException的根本原因是C++与C#的结构体内存布局不匹配,以及参数传递方式错误:
- 结构体数组类型不匹配:C中
AES_ctx的RoundKey和Iv是嵌入式固定大小数组(连续内存块),但C#中直接用byte[]是引用类型,存储的是托管堆指针而非实际数组内容,导致C函数读写错误内存地址。 - 参数传递方式错误:C函数接收的是
struct AES_ctx*指针,但C#传递的是AES_ctx值类型,会导致结构体被拷贝,C函数修改的是无效的副本内存,引发访问错误。 - 潜在架构不匹配:若C#项目编译架构(x86/x64)与DLL不一致,也会导致内存寻址错误。
修复步骤
1. 明确C++端的AES_ctx结构体定义
确保C++中的结构体使用固定大小数组,以AES-256为例:
// DLLCreation.h 补充结构体定义 typedef unsigned char uint8_t; struct AES_ctx { uint8_t RoundKey[240]; // AES-256轮密钥固定为240字节 uint8_t Iv[16]; // IV固定为16字节 }; extern "C" __declspec(dllexport) void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key); extern "C" __declspec(dllexport) void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf);
2. 修正C#端的结构体定义
使用[MarshalAs]属性指定固定大小数组,确保内存布局与C++完全一致:
using System.Runtime.InteropServices; class Program { [StructLayout(LayoutKind.Sequential)] struct AES_ctx { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 240)] public byte[] RoundKey; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] Iv; }; // 可选:使用unsafe固定数组(需开启项目"允许不安全代码"选项) // [StructLayout(LayoutKind.Sequential)] // unsafe struct AES_ctx // { // public fixed byte RoundKey[240]; // public fixed byte Iv[16]; // };
3. 修改DllImport的参数传递方式
将AES_ctx参数改为ref(对应C的指针),确保C函数直接操作C#结构体的内存:
private const string dllPath = "C:\\Users\\RnD User\\source\\repos\\RizwanCodeDLL\\x64\\Debug\\DLLCreation.dll"; [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)] static extern void AES_init_ctx(ref AES_ctx ctx, byte[] key); [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)] static extern void AES_ECB_encrypt(ref AES_ctx ctx, byte[] buf);
4. 调整调用逻辑
无需手动初始化结构体数组(Marshal会自动分配对应大小内存),直接传递引用:
public static byte[] MarshalUnsignedCharArray(byte[] IV, byte[] key) { AES_ctx ctx = new AES_ctx(); AES_init_ctx(ref ctx, key); AES_ECB_encrypt(ref ctx, IV); return IV; }
5. 确保编译架构一致
在C#项目属性的"生成"选项中,将"平台目标"设置为x64(与DLL编译架构匹配),避免位数不匹配导致的内存错误。
内容的提问来源于stack exchange,提问作者umair ijaz
相关产品推荐
相关产品推荐

