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

C#中使用StructLayout从内存取字符串仅返回单个字符问题排查

问题分析与解决方案

看起来你遇到的问题是通过StructLayout读取内存字符串时只拿到了第一个字符"T",而预期是"TEZ",这大概率和内存中字符串的编码格式、终止符,或者FieldOffset的准确性有关,我们来一步步解决:

可能的原因

  1. 编码不匹配:C#的string默认基于UTF-16(宽字符),如果内存中的"TEZ"是以UTF-16存储的,那每个字符占2字节——第一个字符'T'是0x54 0x00,此时用sbyte*读取会把0x00当成ASCII的终止符,自然只读到第一个字符。
  2. 缺少终止符:如果内存中的字符串是ASCII/UTF-8格式,但没有以\0(null字节)结尾,new string(sbyte*)可能会提前终止,或者读取到乱码,但这里只读到第一个字符,更可能是编码问题。
  3. FieldOffset错误:0x14这个偏移量可能并没有准确指向字符串的起始位置,导致你读的是其他内存区域的内容。

针对性解决方案

方案1:如果内存中是UTF-16(宽字符)格式

把结构体里的sbyte数组改成char数组(因为char在C#中就是UTF-16的16位字符):

[StructLayout(LayoutKind.Explicit)]
public unsafe struct InfoDetails
{
    [FieldOffset(0x14)]
    public fixed char Name[50]; // 替换为char数组

    public string getName
    {
        get
        {
            fixed (char* namePtr = Name)
            {
                return new string(namePtr); // 直接读取UTF-16字符串
            }
        }
    }
}

方案2:如果内存中是ASCII/UTF-8格式且无终止符

如果确定是单字节编码,但内存里没有\0终止符,就手动指定读取长度(比如你预期的3个字符):

[StructLayout(LayoutKind.Explicit)]
public unsafe struct InfoDetails
{
    [FieldOffset(0x14)]
    public fixed sbyte Name[50];

    public string getName
    {
        get
        {
            fixed (sbyte* namePtr = Name)
            {
                // 读取前3个字节并转换为字符串
                return Encoding.ASCII.GetString(new ReadOnlySpan<sbyte>(namePtr, 3));
                // 如果是UTF-8就用Encoding.UTF8.GetString
            }
        }
    }
}

额外检查点

  • 确认FieldOffset(0x14)的准确性:可以用调试工具查看内存地址,验证0x14偏移位置是否真的是"T"的起始字节(ASCII的'T'是0x54)。
  • 检查内存中的字符串结构:有些内存布局会先存储字符串长度,再存内容,这种情况需要先读取长度值,再根据长度读取对应字节数的内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:23:50