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

C#接收C端网络传输char*经Marshal转string乱码问题排查

C#对接C服务端时char*转字符串乱码/访问异常问题

问题场景

开发对接C语言编写服务端的C#客户端应用时,其余基础数据类型传输解析均正常,仅C端char*类型字段转换为C#字符串时出现异常。

原有收发实现逻辑

C端(服务端)实现

采用结构体封装待传输数据,原始结构体定义:

struct NetworkRequest {
    int value;
    char *testCharPointer;
};

发送时直接将结构体强制转换为char*类型缓冲区通过网络发送,转换代码:

char *buffer = (char *) (void *)request;

C#端(客户端)实现

收到字节数组后,通过Marshal类将字节数组反序列化为对应结构体,转换代码:

static NetworkRequest convertToRequest(byte[] arr)
{
    NetworkRequest str = new NetworkRequest();

    int size = Marshal.SizeOf(str);
    IntPtr ptr = IntPtr.Zero;
    try
    {
        ptr = Marshal.AllocHGlobal(size);

        Marshal.Copy(arr, 0, ptr, size);

        str = (NetworkRequest)Marshal.PtrToStructure(ptr, str.GetType());
    }
    finally
    {
        Marshal.FreeHGlobal(ptr);
    }

    return str;
}

异常现象

  • 除char*/string映射字段外,其余基础类型字段解析完全正常
  • C端发送内容为hello的char*字段时,C#端控制台打印得到乱码QÈüìt
  • 曾尝试给C#结构体字符串字段加[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]标记,对应C#结构体定义如下:
struct NetworkRequest
{
    public int value;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)] public string testString;
};

如果移除该MarshalAs特性,会直接触发System.AccessViolationException异常。

问题根因

发送结构体时传输的是char*指针本身存储的进程内内存地址,而非指针指向的实际字符串内容。
跨网络传输时,C端进程的独立内存地址对C#端进程完全无效,收到的地址值指向C#进程自身内存空间的随机位置,自然会读取出乱码;直接按无效指针访问内存就会触发访问违例异常。之前尝试用ByValTStr标记的方案本质是按值解析定长字符串内存,和当前传过来的指针值内存布局完全不匹配,也无法正确解析。

修复方案

将C端结构体中的char*指针替换为定长char数组,让字符串内容直接内联存储在结构体内存空间中,发送时随结构体整体被拷贝到缓冲区即可正常传输。
修改后的C端结构体示例:

#define MAX_STR_LEN 100
struct NetworkRequest {
    int value;
    char testCharArr[MAX_STR_LEN];
};

注意C端定长数组的长度需要和C#端SizeConst配置的值保持一致,避免结构体内存布局错位导致解析异常,对应C#端保持原有ByValTStr的Marshal标记即可正常解析字符串内容。

内容的提问来源于stack exchange,提问作者ARandomPerson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 19:48:34