相关疑难解决方法(0)

为什么结构对齐取决于字段类型是原始类型还是用户定义的?

Noda Time v2中,我们正在转向纳秒分辨率.这意味着我们不能再使用8字节整数来表示我们感兴趣的整个时间范围.这促使我调查Noda Time的(很多)结构的内存使用情况,这反过来又导致了我在CLR的对齐决定中发现一点点奇怪.

首先,我意识到这一个实现决策,并且默认行为可能随时发生变化.我意识到我可以使用[StructLayout]和修改它[FieldOffset],但我想提出一个解决方案,如果可能的话不需要它.

我的核心方案是我有一个struct包含引用类型字段和另外两个值类型字段,其中这些字段是简单的包装器int.我希望,这将被表示为对64位的CLR(8用于参考和4每个其他)16个字节,但由于某些原因它使用24个字节.顺便说一下,我正在使用数组测量空间 - 我知道布局在不同的情况下可能会有所不同,但这感觉就像一个合理的起点.

这是一个展示问题的示例程序:

using System;
using System.Runtime.InteropServices;

#pragma warning disable 0169

struct Int32Wrapper
{
    int x;
}

struct TwoInt32s
{
    int x, y;
}

struct TwoInt32Wrappers
{
    Int32Wrapper x, y;
}

struct RefAndTwoInt32s
{
    string text;
    int x, y;
}

struct RefAndTwoInt32Wrappers
{
    string text;
    Int32Wrapper x, y;
}    

class Test
{
    static void Main()
    {
        Console.WriteLine("Environment: CLR {0} …
Run Code Online (Sandbox Code Playgroud)

.net c# clr struct memory-alignment

121
推荐指数
3
解决办法
6859
查看次数

DateTime可以在64位环境中撕裂吗?

在C#设置中,只要变量的大小最大native int(即32位运行时环境中的4个字节和64位上的8个字节),变量的值就是原子级.在一个64位的环境,它包括所有的引用类型和最内置值类型(byte,short,int,long,等等).

设置更大的值不是原子的,并且可能导致仅更新部分内存的撕裂.

DateTime是一个结构,它只包含一个ulong包含其所有数据(TicksDateTimeKind)的字段,并且ulong在64位环境中本身是原子的.

这是否意味着它DateTime也是原子的?或者以下代码是否会在某些时候导致撕裂?

static DateTime _value;
static void Main()
{
    for (int i = 0; i < 10; i++)
    {
        new Thread(_ =>
        {
            var random = new Random();
            while (true)
            {
                _value = new DateTime((long)random.Next() << 30 | (long)random.Next());
            }
        }).Start();
    }

    Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)

.net c# concurrency datetime tearing

51
推荐指数
2
解决办法
2856
查看次数

为什么System.DateTime结构具有布局类型Auto?

结构System.DateTime及其表兄System.DateTimeOffset的结构布局类型设置为"自动".这可以看作:

typeof(DateTime).IsAutoLayout    /* true */
Run Code Online (Sandbox Code Playgroud)

要么:

typeof(DateTime).StructLayoutAttribute.Value    /* Auto */
Run Code Online (Sandbox Code Playgroud)

或者从IL中可以看出它声明:

.class public auto ansi serializable sealed beforefieldinit System.DateTime
              ¯¯¯¯
Run Code Online (Sandbox Code Playgroud)

通常,使用C#编写的结构(即不是枚举的.NET值类型)将具有"顺序"布局(除非StructLayoutAttribute已应用指定另一个布局).

我通过一些常见的搜索BCL组件,以及DateTimeDateTimeOffset是唯一公开可见的结构,我发现用这个布局.

有谁知道为什么DateTime这个不寻常的结构布局?

.net c# datetime struct structlayout

14
推荐指数
1
解决办法
904
查看次数

当子结构具有LayoutKind.Explicit时,不遵循LayoutKind.Sequential

运行此代码时:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace StructLayoutTest
{
    class Program
    {
        unsafe static void Main()
        {
            Console.WriteLine(IntPtr.Size);
            Console.WriteLine();


            Sequential s = new Sequential();
            s.A = 2;
            s.B = 3;
            s.Bool = true;
            s.Long = 6;
            s.C.Int32a = 4;
            s.C.Int32b = 5;

            int* ptr = (int*)&s;
            Console.WriteLine(ptr[0]);
            Console.WriteLine(ptr[1]);
            Console.WriteLine(ptr[2]);
            Console.WriteLine(ptr[3]);
            Console.WriteLine(ptr[4]);
            Console.WriteLine(ptr[5]);
            Console.WriteLine(ptr[6]);
            Console.WriteLine(ptr[7]);  //NB!


            Console.WriteLine("Press any key");
            Console.ReadKey();
        }

        [StructLayout(LayoutKind.Explicit)]
        struct Explicit
        {
            [FieldOffset(0)]
            public int Int32a;
            [FieldOffset(4)]
            public int Int32b;
        }

        [StructLayout(LayoutKind.Sequential, Pack …
Run Code Online (Sandbox Code Playgroud)

.net c# unsafe structlayout layoutkind.explicit

13
推荐指数
1
解决办法
1655
查看次数