2012-09-06 95 views
2

假設我有一個MemoryStream和對字節進行操作的函數。安全地訪問MemoryStream中的數據

當前的代碼是這樣的:

void caller() 
{ 
    MemoryStream ms = // not important 
    func(ms.GetBuffer(), 0, (int)ms.Length); 
} 

void func(byte[] buffer, int offset, int length) 
{ 
    // not important 
} 

我不能改變func但我想,以儘量減少從func內改變數據流的可能性。

我該如何/應該重寫代碼以確保流數據不會被更改?

或者這不能做?

編輯:

我很抱歉,我沒有提到一個我想不使數據的副本。

回答

5

致電.ToArray

func(ms.GetBuffer().ToArray(), 0, (int)ms.Length); 

MSDN(重點煤礦):

注意,緩衝區包含分配的字節,這可能是未使用的。 例如,如果將字符串「test」寫入到MemoryStream 對象中,則從GetBuffer返回的緩衝區的長度爲256,而不是 4,未使用252個字節。 要僅獲取緩衝區中的數據,請使用 ToArray方法;但是,ToArray會在內存中創建數據的副本。


理想情況下,你會改變func採取的IEnumerable<byte>。一旦一個方法擁有數組,你就相信他們不會修改數據,如果你不希望它們。如果合同以提供IEnumerable<byte>,則實施者將不得不決定他們是否需要副本進行編輯。

2

使用ms.ToArray()將數據從流中複製出來。很明顯,會有一個性能問題。

2

您不能僅將數組的「切片」傳遞給方法。無論您通過陣列的方法的副本,並將結果複製回:

byte[] slice = new byte[length]; 
Buffer.BlockCopy(bytes, offset, slice, 0, length); 
func(slice, 0, length); 
Buffer.BlockCopy(slice, 0, bytes, offset, length); 

,或者,如果你可以改變的方法,你通過某種代理對象,它包裝的每個訪問,如果陣列和檢查這是允許的範圍內:

class ArrayView<T> 
{ 
    private T[] array; 
    private int offset; 
    private int length; 

    public T this[int index] 
    { 
     get 
     { 
      if (index < offset || index >= offset + length) 
       throw new ArgumentOutOfRange("index"); 
      return array[index]; 
     } 
     set 
     { 
      if (index < offset || index >= offset + length) 
       throw new ArgumentOutOfRange("index"); 
      array[index] = value; 
     } 
    } 
} 
3

如果你不能讓一個副本(ToArray的在其他的答案建議),不能改變func功能的簽名的唯一剩下的就是嘗試驗證功能做不改變數據。

你可能在調用之前/之後計算某種散列,並檢查它是否相同。它不能保證函數沒有改變底層數據(由於哈希衝突),但至少會給你很好的機會知道它是否發生。可能對非生產代碼有用...

真正的解決方案是提供數據副本到不可信代碼或傳遞一些不允許數據更改的包裝接口/對象(需要簽名更改/重寫func)。

+0

+1以後驗證是一個好主意! – dtb

0

您是否試圖確保func()永遠不會改變內存流,或者如果您的代碼可以拋出異常,如果更改了什麼?聽起來像你想做的事情一樣:

void caller() 
{ 
    MemoryStream ms = // not important 
    var checksum = CalculateMyChecksum(ms); 
    func(ms.GetBuffer(), 0, (int)ms.Length); 
    if(checksum != CalculateMyChecksum(ms)){ 
     throw new Exception("Hey! Someone has been fiddling with my memory!"); 
    } 
} 

我不會覺得舒服的建議這對任何重要/重要的事情。你能提供更多的信息嗎?也許有更好的解決方案來解決你的問題,並且完全避免這個問題。