gpt4 book ai didi

c# - Structlayout 在调试版本中表现不正确

转载 作者:行者123 更新时间:2023-11-30 14:44:50 25 4
gpt4 key购买 nike

考虑以下程序:

using System.Runtime.InteropServices;
using System;
public class Program
{
public static void Main()
{
new magic
{
S = "Hello",
C =
{
[0] = 'W',
[1] = 'o',
[2] = 'r',
[3] = 'l',
[4] = 'd',
}
};

Console.WriteLine("Hello");
Console.ReadKey();
}

[StructLayout(LayoutKind.Explicit)]
struct magic
{
[FieldOffset(0)]
public string S;

[FieldOffset(0)]
public char[] C;
}
}

为什么在使用调试构建时打印 HeWorWorld(如预期)发布?使用 .net 4.8 在 VS 2019 上测试

我知道这样做不仅仅是临界点,但这背后有什么解释吗?

最佳答案

对此没有有效的“预期”结果;行为完全未定义;正在发生的事情是您正在分配一个对 S 的字符串引用(显然也是 C),然后说谎并与数组索引器代码对话,但针对字符串的实例 执行。因为这是实习 "Hello" , 你正在覆盖全局实习 "Hello" ,但是:数组索引器操作码只知道如何与数组对话,因此得到的偏移量是错误的。字符串和数组的内部布局可能不同(很明显,这取决于运行时、框架版本等),因此它可以(并且确实)更新从对象头的错误偏移量开始的字节。

至于为什么它在某些设置上有效:同样是未定义的行为。允许未定义的行为“起作用”,其中空引号很重要。

如果你想正确得到偏移量,那么要么使用fixedToSpan()/ToMemory() .第一个允许 string被视为 char* ;第二个允许 string被视为 ReadOnlySpan<char> (但您可以使用 MemoryMarshalReadOnlyMemory<char> 升级为 Memory<char> )。

例子:

Console.WriteLine("Hello"); // Hello

// note: using MemoryMarshal.* is like using Unsafe.*; you
// are explicitly accepting the consequences if used incorrectly
var span = MemoryMarshal.AsMemory("Hello".AsMemory()).Span;
span[0] = 'W';
span[1] = 'o';
span[2] = 'r';
span[3] = 'l';
span[4] = 'd';
Console.WriteLine("Hello"); // World

// ditto, "unsafe" means you're accepting the consequences
fixed(char* c = "Hello")
{
c[0] = 'd';
c[1] = 'l';
c[2] = 'r';
c[3] = 'o';
c[4] = 'W';
}
Console.WriteLine("Hello"); // dlroW

另外,大概真的不需要说,但是...不要这样做!

关于c# - Structlayout 在调试版本中表现不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56869975/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com