You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 16:15:55