2012-01-25 43 views
2

讓我們假定以下CIL程序:CIL和陣列邊界檢查

.assembly extern mscorlib {} 
.assembly Program {} 

.method private static void Main() cil managed 
{ 
    .entrypoint 
    .maxstack 4 

    .locals init (int32[] a, 
       uint32 t) 

    // Creates an array of int of size 10 
    ldc.i4 10 
    newarr int32 
    stloc.0 

    // Writes 0xaabbccdd at the index 2 of the array 
    ldloc.0 
    ldc.i4.2 
    ldc.i4 0xaabbccdd 
    stelem.i4 

    // Loads 
    ldloc.0 
    ldc.i4 9 // <HERE> 
    ldelem.i1 

    stloc.1 
    ldstr "Value: 0x{0:x8}" 
    ldloc.1 
    box [mscorlib]System.UInt32 
    call void [mscorlib]System.Console::WriteLine(string, object) 

    ret 
} 

此程序:

  • 創建INT尺寸的陣列10
  • 在陣列的索引2中寫入0xaabbccdd
  • 嘗試使用ldelem.i1讀取陣列中的一個字節
  • 打印結果

訣竅是我使用「ldelem.i1」而不是更標準的「idelem.i4」來處理性能問題(我想避免做掩碼)這個想法是以訪問數組的方式訪問數據一個用C中的指針來做。

但事情並不好,因爲程序崩潰(IndexOutOfRangeException)超過10作爲ldelem.i1參數的索引。 這個男人的竅門沒用,因爲我無法訪問第三個索引整數前半部分後的數據。

理想情況下,我想訪問字節達39指數,其對應於整數的最後一個字節在指數9

我將非常感謝,如果有人對這個問題的一些想法。

回答

3

有趣。在ECMA-335規定,如果索引大於或等於所述陣列的尺寸,這絕對是它將拋出異常。令我驚訝的關於這不是拋出異常,但該指數被視爲字節指數爲INT數組的第一個地方 - 我不能看到多數民衆贊成在任何地方規定。

嫌疑你進入的未指定的行爲,很可能的行爲是不打算指定的領域 - 我懷疑你只是無意的int陣列上使用ldelem.i1

+0

謝謝你的評論。我可以想象它是如何在引擎蓋下實施的,而且我也得出了和你一樣的結論。你能想到另一種方法來達到預期的行爲嗎? –

+1

對於替代,MS C++/CLI使用空結構以'StructLayout(LayoutKind.Explicit,大小= ...)'屬性和指針操作使用'LD * A','add'和'ldind。*'/ 'stind *'。 – hvd

+0

@AntoineTrouve:你可以使用C#中的不安全代碼,臨時修改數組 - 然後從'int *'強制轉換爲'byte *'。 –