欢迎您! | 积分 | 主页 |
注册 | 登陆 |
官方QQ群: 8807551
学教

.Net中unsafe编程详解

发布日:2010-06-08 20:42:46.0 发布人:don 浏览量:151

类别: IT电脑开发

标签: .net unsafe 编程

点击放大图片-.Net中unsafe编程详解

以c#为例。

一,打开unsafe编程开关

   工程中默认的配置是不支持代码的非安全性的,所以第一次使用你得:

      解决方案管理器→→Properties→→生成选项卡→→允许不安全代码。

二,何时要用unsafe

1.一个原则

   unsafe  关键字表示不安全上下文,该上下文是任何涉及指针的操作所必需的。我的想法就是一旦你得用指针就必须用unsafe。

2.什么时候用指针

    msdn里说 “在 C# 中很少需要使用指针,但仍有一些需要使用的情况。例如,在下列情况中使用允许采用指针的不安全上下文是正确的: 处理磁盘上的现有结构, 涉及内部包含指针的结构的高级 COM 或平台调用方案, 性能关键代码, 对于第一和第二点,主要是调win32的api。”

   总之,一条判断标准:当你使用C/C++能给带给你的利大于弊时都可以使用unsafe编程,呵呵。

三,unsafe的使用方法(几个例子)

1.unsafe一个方法体

  1.  1. class UnsafeTest1    
  2.  2. {    
  3.  3. unsafe static void AddParam(int *a)    
  4.  4. {    
  5.  5. *a = *a 10000;    
  6.  6. } .    
  7.  7. unsafe public static void Main()    
  8.  8. {    
  9.  9. int i = 10000;    
  10. 10. AddParam (&i);    
  11. 11. Console.WriteLine(i);    
  12. 12. }    
  13. 13. }   

2.unsafe一段代码

  1. private void button1_Click(object sender, EventArgs e)  
  2. {  
  3.     unsafe  
  4.     {  
  5.         int *pInt;  
  6.     }  
  7. }  

3.网上找的一个较大unsafe例子

代码
   1using System;  
   
2using System.Collections.Generic;  
   
3using System.Text;  
   
4namespace UnsafeCode  
   
5. {  
   
6.   #region Unsafe types and members (just for testing purposes)  
   
7.   // This entire structure is 'unsafe' and can  
   8.   // be used only in an unsafe context.  
   9.   public unsafe struct Node  
  
10.   {  
  
11.     public int Value;  
  
12.     public Node* Left;  
  
13.     public Node* Right;  
  
14.   }  
  
15.   // This struct is safe, but the Node* members  
  16.   // are not. Technically, you may access 'Value' from  
  17.   // outside an unsafe context, but not 'Left' and 'Right'.  
  18.   public struct Node2  
  
19.   {  
  
20.     public int Value;  
  
21.     // These can be accessed only in an unsafe context!  
  22.     public unsafe Node2* Left;  
  
23.     public unsafe Node2* Right;  
  
24.   }  
  
25.   #endregion  
  
26.   #region Simple Point / PointRef  
  
27.   struct Point  
  
28.   {  
  
29.     public int x;  
  
30.     public int y;  
  
31.     public override string ToString()  
  
32.     { return string.Format("({0}, {1})", x, y); }  
  
33.   }  
  
34.   class PointRef  
  
35.   {  
  
36.     public int x;  
  
37.     public int y;  
  
38.     public override string ToString()  
  
39.     { return string.Format("({0}, {1})", x, y); }  
  
40.   }    
  
41.   #endregion  
  
42.   class Program  
  
43.   {  
  
44.     static void Main(string[] args)  
  
45.     {  
  
46.       Console.WriteLine("***** Fun with Pointers *****");  
  
47.       #region Swap 2 ints safely and unsafely  
  
48.       // Values for swap.  
  49.       int i = 10, j = 20;  
  
50.       // Swap values 'safely'.  
  51.       Console.WriteLine("\n***** Safe swap *****");  
  
52.       Console.WriteLine("Values before safe swap: i = {0}, j = {1}", i, j);  
  
53.       SafeSwap(ref i, ref j);  
  
54.       Console.WriteLine("Values after safe swap: i = {0}, j = {1}", i, j);  
  
55.       // Swap values 'unsafely'.  
  56.       Console.WriteLine("\n***** Unsafe swap *****");  
  
57.       Console.WriteLine("Values before unsafe swap: i = {0}, j = {1}", i, j);  
  
58.       unsafe { UnsafeSwap(&i, &j); }  
  
59.       Console.WriteLine("Values after unsafe swap: i = {0}, j = {1}", i, j);  
  
60.       Console.WriteLine();  
  
61.       #endregion  
  
62.       UsePointerToPoint();  
  
63.       Console.WriteLine();  
  
64.       UseSizeOfOperator();  
  
65.       Console.ReadLine();  
  
66.     }  
  
67.     public static void SafeSwap(ref int i, ref int j)  
  
68.     {  
  
69.       int temp = i;  
  
70.       i = j;  
  
71.       j = temp;  
  
72.     }  
  
73.     #region Various unsafe methods  
  
74.     unsafe static void PrintValueAndAddress()  
  
75.     {  
  
76.       int myInt;  
  
77.       // Define an int pointer, and  
  78.       // assign it the address of myInt.  
  79.       int* ptrToMyInt = &myInt;  
  
80.       // Assign value of myInt using pointer indirection.  
  81.       *ptrToMyInt = 123;  
  
82.       // Print some stats.  
  83.       Console.WriteLine("Value of myInt {0}", myInt);  
  
84.       Console.WriteLine("Address of myInt {0:X}", (int)&ptrToMyInt);  
  
85.     }  
  
86.     unsafe static void SquareIntPointer(int* myIntPointer)  
  
87.     {  
  
88.       // Work with pointer types here!  
  89.       // Square the value just for a test.  
  90.       *myIntPointer *= *myIntPointer;  
  
91.     }  
  
92.     unsafe public static void UnsafeSwap(int* i, int* j)  
  
93.     {  
  
94.       int temp = *i;  
  
95.       *= *j;  
  
96.       *= temp;  
  
97.     }  
  
98.     unsafe static void UsePointerToPoint()  
  
99.     {  
 
100.       // Access members via pointer.  
 101.       Point point;  
 
102.       Point* p = &point;  
 
103.       p->= 100;  
 
104.       p->= 200;  
 
105.       Console.WriteLine(p->ToString());  
 
106.       // Access members via pointer indirection.  
 107.       Point point2;  
 
108.       Point* p2 = &point2;  
 
109.       (*p2).x = 100;  
 
110.       (*p2).y = 200;  
 
111.       Console.WriteLine((*p2).ToString());  
 
112.     }  
 
113.     unsafe static void UnsafeStackAlloc()  
 
114.     {  
 
115.       char* p = stackalloc char[256];  
 
116.       for (int k = 0; k < 256; k++)  
 
117.         p[k] = (char)k;  
 
118.     }  
 
119.     unsafe public static void UseAndPinPoint()  
 
120.     {  
 
121.       PointRef pt = new PointRef();  
 
122.       pt.x = 5;  
 
123.       pt.y = 6;  
 
124.       // pin pt in place so it will not  
 125.       // be moved or GC-ed.  
 126.       fixed (int* p = &pt.x)  
 
127.       {  
 
128.         // Use int* variable here!  
 129.       }  
 
130.       // pt is now unpinned, and ready to be GC-ed.  
 131.       Console.WriteLine("Point is: {0}", pt);  
 
132.     }  
 
133.     unsafe static void UseSizeOfOperator()  
 
134.     {  
 
135.       Console.WriteLine("The size of short is {0}."sizeof(short));  
 
136.       Console.WriteLine("The size of int is {0}."sizeof(int));  
 
137.       Console.WriteLine("The size of long is {0}."sizeof(long));  
 
138.       Console.WriteLine("The size of Point is {0}."sizeof(Point));  
 
139.     }  
 
140.     #endregion  
 
141.   }  
 
142. }  

四,使用unsafe时可能用到的fixed

   1.为什么要用fixed

       Unsafe的代码托管代码 (managed code)和非托管代码(Unmanaged Code)之间,它也是在CLR的环境中执行,但是可以用来直接操作内存。但由于代码是在CLR下托管执行,为了减少内存碎片C#的自动垃圾回收机制会允 许已经分配的内存在运行时进行位置调整,所以如果我们多次调用的话就可能 导致指针指向其他的变量。比如*pInt为指向一个变量的地址为1001,CLR在重新内存整理分配后该变量就存储在地址为5001的地方。而原来 1001的地方可能会被分配其他变量,要解决这个问题我们就需要使用Fixed关键字。

   2.使用fixed的例子

      fixed 语句禁止垃圾回收器重定位可移动的变量。fixed 语句只能出现在不安全的上下文中。Fixed 还可用于创建固定大小的缓冲区。

  1. using System;  
  2. class CaryData  
  3. {  
  4.     public int data;  
  5. }  
  6. class CProgram  
  7. {  
  8.      
  9.     unsafe static void ChangeValue(int* pInt)  
  10.     {  
  11.         *pInt = 23;  
  12.     }  
  13.     public unsafe static void Main()  
  14.     {  
  15.         CaryData cd = new CaryData();  
  16.         Console.WriteLine("改变前: {0}", cd.data);          
  17.         fixed (int* p = &cd.data)  
  18.         {  
  19.             ChangeValue(p);  
  20.         }  
  21.         Console.WriteLine("改变后: {0}", cd.data);  
  22.     }  
  23. }  

五,参考

1.http://msdn.microsoft.com/zh-cn/library/chfa2zb8.aspx

2.http://msdn.microsoft.com/zh-cn/library/f58wzh21.aspx

3.http://www.tzwhx.com/newOperate/html/1/12/123/19847.html



验证码:验证码

店名:Don的知识网店
店主:don

©2008 - 沪ICP备07037037号 - 王晓东 - SQL管理 - 邮箱登陆 - RSS阅读