<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      happyhippy

      這個世界的問題在于聰明人充滿疑惑,而傻子們堅信不疑。--羅素


          前幾天,我介紹了托管環境下struct實例的Layout和Size,其中介紹了StructLayoutAttribute特性,其實StructLayoutAttribute特性不只可以用在struct上,也可以用在class上,下面介紹下將StructLayoutAttribute運用在引用類型上時,對象實例的一些行為。

          在.net托管環境下,CRL像一個黑箱一樣,將我們創建的對象丟在這個暗箱中進行操作,我們不能直接獲得對象實例中字段的布局(Layout)和對象實例的size,但是我們可以通過Visual Studio+SOS擴展來進行非托管代碼調試,并獲得對象的這些信息。如果對非托管代碼調試還不了解,可以參考我以前寫的一篇《使用SOS - 在Visual Studio中啟用非托管代碼調試來支持本機代碼調試》。

          默認情況下,C#編譯器會在引用類型上運用[StructLayoutAttribute(LayoutKind.Auto)]特性,即按照CLR認為的最佳方式來排序實例中的字段順序;當運用[StructLayout(LayoutKind.Sequential)]特性時,CLR會按照字段成員在被導出到非托管內存時出現的順序依次布局,但我的測試結果是:貌似使用LayoutKind.Sequential與使用LayoutKind.Auto的結果相同;當運用[StructLayout(LayoutKind.Explicit)]時,我們可以自己設置實例中字段的位置。下面通過實例來進行分析:

      //測試代碼:
      namespace Debug
      {
          
      class ClassAuto//C#編譯器會自動在上面運用[StructLayout(LayoutKind.Auto)]
          {
              
      public bool b1;  //1Byte
              public double d;//8byte
              public bool b2;  //1byte
          }


          [StructLayout(LayoutKind.Sequential)]
          
      class ClassSeqt
          
      {
              
      public bool b1;  //1Byte
              public double d;//8byte
              public bool b2;  //1byte
          }


          [StructLayout(LayoutKind.Explicit)]
          
      class ClassExpt1
          
      {
              [FieldOffset(
      0)]
              
      public bool b1;  //1Byte
              [FieldOffset(0)]
              
      public double d;//8byte
              [FieldOffset(8)]
              
      public bool b2;  //1byte
          }


          [StructLayout(LayoutKind.Explicit)]
          
      class ClassExpt2
          
      {
              [FieldOffset(
      0)]
              
      public bool b1;  //1Byte
              [FieldOffset(0)]
              
      public double d;//8byte
              [FieldOffset(0)]
              
      public bool b2;  //1byte
          }


          
      static class Program
          
      {
              [STAThread]
              
      static void Main()
              
      {
                  ClassAuto deft 
      = new ClassAuto();
                  ClassSeqt auto 
      = new ClassSeqt();
                  ClassExpt1 expt1 
      = new ClassExpt1();
                  ClassExpt2 expt2 
      = new ClassExpt2();
                  
      return;  //注意:在這一行設置斷點
              }

          }

      }

       

          在進行測試之前,我先按照《托管環境下struct實例的Layout和Size》和《類型實例的創建位置、托管對象在托管堆上的結構》兩篇文中的理論來猜測了下這四個對象的Size:
          CLR為每個對象添加SyncblkIndex和TypeHandle兩個字段各占了4byte空間,合計8byte(有關SyncblkIndex和TypeHandle兩個字段的討論,可以參考《類型實例的創建位置、托管對象在托管堆上的結構》);
          對于在引用類型上應用默認的[StructLayout(LayoutKind.Auto)]特性情況,CLR應該會將兩個bool型變量b1和b2放到相鄰的位置中,因此ClassAuto的size應該是4(SyncblkIndex)+4(TypeHandle)+8(double d) + 1(bool b1) + 1(bool b2) + 2(4byte內存對齊)=20byte
          對于在引用類型上應用[StructLayout(LayoutKind.Sequential)]的情況,既然聲明了布局順序與聲明順序相同,則需要兩個byte變量上的都要進行4byte的內存對齊,ClassSeqt的size應該是:4(SyncblkIndex)+4(TypeHandle)+1(bool b1) +3(4byte內存對齊) + 8(double d) + + 1(bool b2) + 3(4byte內存對齊)=24byte
          對于在引用類型上應用[StructLayout(LayoutKind.Explicit)]的情況,套用“在struct上應用[StructLayout(LayoutKind.Explicit)]時不會進行任何填充”的結論,ClassExpt1的size應該是4(SyncblkIndex)+4(TypeHandle)+8(double d,b1被d吃掉了) + 1(bool b2)=17byte;ClassExpt2的size應該是4(SyncblkIndex)+4(TypeHandle)+8(double d,b1和b2都被d吃掉了)=16byte
          我猜測這四個對象的內存布局圖如下所示:



          上面僅僅只是我猜測的結果,但實際的測試結果并不完全是這樣的,下面是測試過程:

          編譯上面的代碼,在Main函數的“return;”語句處設置斷點,按F5進入Debug調試模式,程序運行到斷點處中止;然后我們通過“菜單->Debug->Windows->Immediate”打開“Immediate Window”,在該窗口中先輸入“.load sos”來啟用非托管代碼調試,提示已加載SOS.dll擴展后再輸入“!DumpHeap -type Class”,此時會輸出當前進程中類名中包含“Class”字符串的所有對象的信息,如下圖所示:


          第一個表的第一列(Address)列出了這些對象的起始地址,第二列(MT)列出了類型的方法表(Method Table)的起始地址;第二個表的最后一列(Class Name)列出了這些對象的類型名,第一列(MT)列出了類型的方法表地址(跟上面這張表的第二列相同),第二列(Count)列出了當前進程中該對象實例的數量,第三列(Totel Size)內出了該類型的所有實例的總Size。下面就具體對各個對象進行分析:

      1. ClassAuto:[StructLayout(LayoutKind.Auto)]

      >!dumpobj 013e1a88
      Name: Debug.ClassAuto
      MethodTable: 00a530b8
      EEClass: 00a51524
      Size: 
      20(0x14) bytes
       (E:\Project2005\Debug\Debug\bin\Debug\Debug.exe)
      Fields:
            MT    Field   Offset                 Type VT     Attr    Value Name
      79104f64  
      4000004        c       System.Boolean  0 instance        0 b1
      791059c0  
      4000005        4        System.Double  0 instance 0.000000 d
      79104f64  
      4000006        d       System.Boolean  0 instance        0 b2

          其size和Layout跟猜想中的一致(其中第三列Offset列出了該字段的偏移位置),注意,這里是按4byte進行內存對齊,而不是像struct一樣按照成員的最大size進行對齊!

      2. ClassSeqt:[StructLayout(LayoutKind.Sequential)]

      >!dumpobj 013e1a9c
      Name: Debug.ClassSeqt
      MethodTable: 00a53150
      EEClass: 00a51588
      Size: 
      20(0x14) bytes
       (E:\Project2005\Debug\Debug\bin\Debug\Debug.exe)
      Fields:
            MT    Field   Offset                 Type VT     Attr    Value Name
      79104f64  
      4000007        c       System.Boolean  0 instance        0 b1
      791059c0  
      4000008        4        System.Double  0 instance 0.000000 d
      79104f64  
      4000009        d       System.Boolean  0 instance        0 b2

          其size和Layout竟然跟使用[StructLayout(LayoutKind.Auto)]完全一致,也就是說,我上面猜測的24byte的布局是錯誤的,觀察Offset列的值,我們可以看到,double d排在了第一個位置,bool b1排在了d的后面,也就是說CLR仍然按照[StructLayout(LayoutKind.Auto)]對字段進行布局。這是我在.net framework 2.0(Visual Studio 2005)上的測試結果,不知道其他版本的framework會不會是同樣的結果-_-.

      3. ClassExpt1:[StructLayout(LayoutKind.Explicit)]

      >!dumpobj 013e1ab0
      Name: Debug.ClassExpt1
      MethodTable: 00a531e8
      EEClass: 00a51648
      Size: 
      20(0x14) bytes
       (E:\Project2005\Debug\Debug\bin\Debug\Debug.exe)
      Fields:
            MT    Field   Offset                 Type VT     Attr    Value Name
      79104f64  400000a        
      4       System.Boolean  0 instance        0 b1
      791059c0  400000b        
      4        System.Double  0 instance 0.000000 d
      79104f64  400000c        c       System.Boolean  
      0 instance        0 b2

          Layout與我們在類型定義中的設定值一致;size為20byte,說明CLR對其進行了4byte的內存對齊;

      4. ClassExpt2:[StructLayout(LayoutKind.Explicit)]

      >!dumpobj 013e1ac4
      Name: Debug.ClassExpt2
      MethodTable: 00a53280
      EEClass: 00a51708
      Size: 
      16(0x10) bytes
       (E:\Project2005\Debug\Debug\bin\Debug\Debug.exe)
      Fields:
            MT    Field   Offset                 Type VT     Attr    Value Name
      79104f64  400000d        
      4       System.Boolean  0 instance        0 b1
      791059c0  400000e        
      4        System.Double  0 instance 0.000000 d
      79104f64  400000f        
      4       System.Boolean  0 instance        0 b2

         其size和Layout跟猜想中的一致。
         四個對象的實際Layout如下圖所示(根據上面表中的Offset來排的):


          最后補充一點和struct一樣要注意的地方:如果在運用了[StructLayout(LayoutKind.Explicit)],計算FieldOffset一定要小心,例如我們使用上面ClassExpt1來進行下面的測試:

      ClassExpt1 expt1 = new ClassExpt1();
      expt1.d 
      = 0;
      expt1.b1 
      = true;
      Console.WriteLine(expt1.d);

          輸出的結果不再是0了,而是4.94065645841247E-324,這是因為expt1.b1和expt1.d共享了一個byte,執行“expt1.b1 = true;時”也改變了expt1.d,CPU在按照浮點數的格式解析expt1.d時就得到了這個結果。(有關浮點數討論可以參考我以前寫的《精確判斷一個浮點數是否等于0》)。所以在運用LayoutKind.Explicit時千萬別把FieldOffset算錯了:)


         結論:在32位的計算機上,默認情況下,對于引用類型的實例,CLR總是按4byte進行內存對齊

      posted on 2007-04-17 16:42  Silent Void  閱讀(7044)  評論(12)    收藏  舉報

      主站蜘蛛池模板: 亚洲日韩性欧美中文字幕| 一区二区在线观看成人午夜| 国产一级毛片高清完整视频版| 久久99国产亚洲高清观看首页| 一区二区三区岛国av毛片| 国产精品天天看天天狠| 黎平县| 日韩精品一区二区三区蜜臀| 十八禁午夜福利免费网站| 久久久久久久久18禁秘| 亚洲国产成人av国产自| 日韩av一区二区三区在线| 亚洲 a v无 码免 费 成 人 a v| 日韩中文字幕亚洲精品一| 孝义市| 亚洲人成色99999在线观看| 亚洲区欧美区综合区自拍区| 精品国产高清中文字幕| 色综合久久久久综合体桃花网 | 句容市| 日本一区不卡高清更新二区| 国产91丝袜在线播放动漫| 四虎www永久在线精品| 老司机午夜福利视频| 日本丰满老妇bbb| 亚洲精品国产第一区二区| 天天做天天爱夜夜爽导航| 天天色综网| 久久综合综合久久高清免费| 国产高清在线a视频大全| 亚洲激情av一区二区三区| 亚洲熟妇精品一区二区| 国产做无码视频在线观看| 成人午夜大片免费看爽爽爽| 精品 日韩 国产 欧美 视频| 国产午夜福利一区二区三区| 国内精品免费久久久久电影院97| 国产一卡2卡3卡4卡网站精品| 亚洲成人av在线资源网| 亚洲深深色噜噜狠狠网站| 四虎国产精品永久在线看|