[英]Why does this code work without the unsafe keyword?
在回答他自己有爭議的問題時 , Mash已經說明你不需要“unsafe”關鍵字直接讀寫任何.NET對象實例的字節。 您可以聲明以下類型:
[StructLayout(LayoutKind.Explicit)]
struct MemoryAccess
{
[FieldOffset(0)]
public object Object;
[FieldOffset(0)]
public TopBytes Bytes;
}
class TopBytes
{
public byte b0;
public byte b1;
public byte b2;
public byte b3;
public byte b4;
public byte b5;
public byte b6;
public byte b7;
public byte b8;
public byte b9;
public byte b10;
public byte b11;
public byte b12;
public byte b13;
public byte b14;
public byte b15;
}
然后你可以做一些事情,比如改變一個“不可變”的字符串。 以下代碼在我的機器上打印“bar”:
string foo = "foo";
MemoryAccess mem = new MemoryAccess();
mem.Object = foo;
mem.Bytes.b8 = (byte)'b';
mem.Bytes.b10 = (byte)'a';
mem.Bytes.b12 = (byte)'r';
Console.WriteLine(foo);
您還可以通過使用相同的技術破壞對象引用來觸發AccessViolationException 。
問題:我認為(在純托管C#代碼中) unsafe關鍵字是必要的,以執行此類操作。 為什么這里沒有必要? 這是否意味着純粹的托管“安全”代碼根本不安全?
好吧,這是令人討厭的......使用工會的危險。 這可能有用,但不是一個好主意 - 我想我會將它與反射(你可以做大多數事情)進行比較。 我有興趣看看它是否在受限制的訪問環境中工作 - 如果是這樣,它可能代表一個更大的問題......
我剛剛測試它沒有“完全信任”標志,運行時拒絕它:
無法從程序集“ConsoleApplication4,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null”加載類型“MemoryAccess”,因為對象在偏移0處重疊且程序集必須是可驗證的。
要擁有這面旗幟,你已經需要高度信任 - 所以你已經可以做更多討厭的事了。 字符串是一個稍微不同的情況,因為它們不是正常的.NET對象 - 但是還有其他一些方法可以改變它們 - 但“聯合”方法是一個有趣的方法。 對於另一種hacky方式(有足夠的信任):
string orig = "abc ", copy = orig;
typeof(string).GetMethod("AppendInPlace",
BindingFlags.NonPublic | BindingFlags.Instance,
null, new Type[] { typeof(string), typeof(int) }, null)
.Invoke(orig, new object[] { "def", 3 });
Console.WriteLine(copy); // note we didn't touch "copy", so we have
// mutated the same reference
哎呀,我已經fixed
unsafe
了。 這是一個更正版本:
示例代碼不需要使用unsafe
關鍵字進行標記的原因是它不包含指針 (請參閱下面的引用,了解為什么這被認為是不安全的)。 你是完全正確的:“安全”可能更好地被稱為“運行時友好”。 有關此主題的更多信息,我將向您推薦Don Box和Chris Sells Essential .NET
引用MSDN,
在公共語言運行庫(CLR)中,不安全的代碼稱為無法驗證的代碼。 C#中的不安全代碼不一定是危險的; 這只是CLR無法驗證其安全性的代碼。 因此,如果CLR位於完全受信任的程序集中,則它只會執行不安全的代碼。 如果使用不安全的代碼,則您有責任確保代碼不會引入安全風險或指針錯誤。
固定和不安全之間的區別在於固定阻止CLR在內存中移動東西,因此運行時之外的東西可以安全地訪問它們,而不安全則恰恰相反的問題:CLR可以保證正確的解決方案dotnet引用,它不能為指針這樣做。 你可能還記得各種關於引用如何不是指針的微軟,這就是為什么它們會對一個微妙的區別做出如此大驚小怪的原因。
你仍然選擇退出'托管'位。 有一個潛在的假設,如果你能做到那么你知道你在做什么。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.