ImageVerifierCode 换一换
格式:DOCX , 页数:27 ,大小:32.08KB ,
资源ID:18441261      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/18441261.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(C#不安全代码Word文档格式.docx)为本站会员(b****3)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

C#不安全代码Word文档格式.docx

1、 类、结构、接口或委托的声明可以包含一个 unsafe 修饰符,在这种情况下,该类型声明的整个文本范围(包括类、结构或接口的体)被认为是不安全上下文。 在字段、方法、属性、事件、索引器、运算符、实例构造函数、析构函数或静态构造函数的声明中,也可以包含一个 unsafe 修饰符,在这种情况下,该成员声明的整个文本范围被认为是不安全上下文。 unsafe-statement 使得可以在 block 内使用不安全上下文。该语句关联的 block 的整个文本范围被认为是不安全上下文。下面显示了关联的语法扩展。为简洁起见,用省略号 (.) 表示前几章中出现过的产生式。class-modifier:.un

2、safestruct-modifier:interface-modifier:delegate-modifier:field-modifier:method-modifier:property-modifier:event-modifier:indexer-modifier:operator-modifier:constructor-modifier:destructor-declaration:attributesopt externopt unsafeopt identifier ( ) destructor-bodyattributesopt unsafeopt externopt id

3、entifier ( ) destructor-bodystatic-constructor-modifiers:externopt unsafeopt staticunsafeopt externopt staticexternopt static unsafeopt static externopt unsafeoptstatic unsafeopt externoptembedded-statement:unsafe-statementunsafe-statement:unsafe block在下面的示例中public unsafe struct Node public int Valu

4、e; public Node* Left; public Node* Right;在结构声明中指定的 unsafe 修饰符导致该结构声明的整个文本范围成为不安全上下文。因此,可以将 Left 和 Right 字段声明为指针类型。上面的示例还可以编写为public struct Node public unsafe Node* Left; public unsafe Node* Right;此处,字段声明中的 unsafe 修饰符导致这些声明被认为是不安全上下文。除了建立不安全上下文从而允许使用指针类型外,unsafe 修饰符对类型或成员没有影响。public class A public un

5、safe virtual void F() char* p; . public class B: A public override void F() base.F();A 中 F 方法上的 unsafe 修饰符直接导致 F 的文本范围成为不安全上下文并可以在其中使用语言的不安全功能。在 B 中对 F 的重写中,不需要重新指定 unsafe 修饰符,除非 B 中的 F 方法本身需要访问不安全功能。当指针类型是方法签名的一部分时,情况略有不同public unsafe class A public virtual void F(char* p) . public unsafe override

6、void F(char* p) .此处,由于 F 的签名包括指针类型,因此它只能出现在不安全上下文中。然而,为设置此不安全上下文,既可以将整个类设置为不安全的(如 A 中的情况),也可以仅在方法声明中包含一个 unsafe 修饰符(如 B 中的情况)。1.2 指针类型在不安全上下文中,type(第 4 章)可以是 pointer-type,也可以是 value-type 或 reference-type。但是,pointer-type 也能在不安全上下文以外的 typeof 表达式(第 7.5.11 节)中使用,因为此类使用不是不安全的。type:value-typereference-typ

7、epointer-typepointer-type 可表示为 unmanaged-type 后跟一个 * 标记,或者关键字 void 后跟一个 * 标记:pointer-type:unmanaged-type *void *unmanaged-type:type指针类型中,在 * 前面指定的类型称为该指针类型的目标类型 (referent type)。它表示该指针类型的值所指向的变量的类型。与引用(引用类型的值)不同,指针不受垃圾回收器跟踪(垃圾回收器并不知晓指针和它们指向的数据)。出于此原因,不允许指针指向引用或者包含引用的结构,并且指针的目标类型必须是 unmanaged-type。unm

8、anaged-type 是任何不是 reference-type 并且在任何嵌套级别都不包含 reference-type 字段的类型。换句话说,unmanaged-type 是下列类型之一: sbyte、byte、short、ushort、int、uint、long、ulong、char、float、double、decimal 或 bool。 任何 enum-type。 任何 pointer-type。 任何由用户定义的只包含 unmanaged-type 字段的 struct-type。将指针和引用进行混合使用时的基本规则是;引用(对象)的目标可以包含指针,但指针的目标不能包含引用。下表

9、给出了一些指针类型的示例:示例说明byte*指向 byte 的指针char*指向 char 的指针int*指向 int 的指针的指针int*一维数组,它的元素是指向 int 的指针void*指向未知类型的指针对于某个给定实现,所有的指针类型都必须具有相同的大小和表示形式。与 C 和 C+ 不同,在 C# 中,当在同一声明中声明多个指针时,* 只与基础类型写在一起,而不充当每个指针名称的前缀标点符号。例如int* pi, pj; / NOT as int *pi, *pj;类型为 T* 的一个指针的值表示类型为 T 的一个变量的地址。指针间接寻址运算符 * (第 18.5.1 节) 可用于访问此

10、变量。例如,给定int* 类型的变量 P,则表达式 *P 表示 int 变量,该变量的地址就是 P 的值。 与对象引用类似,指针可以是 null。如果将间接寻址运算符应用于 null 指针,则其行为将由实现自己定义。值为 null 的指针表示为将该指针的所有位都置零。void* 类型表示指向未知类型的指针。因为目标类型是未知的,所以间接寻址运算符不能应用于 void* 类型的指针,也不能对这样的指针执行任何算术运算。但是,void* 类型的指针可以强制转换为任何其他指针类型(反之亦然)。指针类型是一个单独类别的类型。与引用类型和值类型不同,指针类型不从 object 继承,而且不存在指针类型和

11、 object 之间的转换。具体而言,指针不支持装箱和拆箱(第 4.3 节)操作。但是,允许在不同指针类型之间以及指针类型与整型之间进行转换。在第 18.4 节中对此进行了描述。pointer-type 可用作易失字段的类型(第 10.4.3 节)。虽然指针可以作为 ref 或 out 参数传递,但这样做可能会导致未定义的行为,例如,指针可能被设置为指向一个局部变量,而当调用方法返回时,该局部变量可能已不存在了;或者指针曾指向一个固定对象,但当调用方法返回时,该对象不再是固定的了。例如:using System;class Test static int value = 20; unsafe

12、static void F(out int* pi1, ref int* pi2) int i = 10; pi1 = &i; fixed (int* pj = &value) / . pi2 = pj; static void Main() unsafe int* px1; int* px2 = & F(out px1, ref px2); Console.WriteLine(*px1 = 0, *px2 = 1, *px1, *px2); / undefined behavior方法可以返回某一类型的值,而该类型可以是指针。例如,给定一个指向连续的 int 值序列的指针、该序列的元素个数,

13、和另外一个 int 值 (value),下面的方法将在该整数序列中查找与该 value 匹配的值,若找到匹配项,则返回该匹配项的地址;否则,它将返回 null:unsafe static int* Find(int* pi, int size, int value) for (int i = 0; i 运算符可用于通过指针访问结构的成员(第 18.5.2 节)。 运算符可用于索引指针(第 18.5.3 节)。 & 运算符可用于获取变量的地址(第 18.5.4 节)。 + 和 - 运算符可以用于递增和递减指针(第 18.5.5 节)。 + 和 - 运算符可用于执行指针算术运算(第 18.5.6

14、节)。 =、!=、 运算符可以用于比较指针(第 18.5.7 节)。 stackalloc 运算符可用于从调用堆栈(第 18.7 节)中分配内存。 fixed 语句可用于临时固定一个变量,以便可以获取它的地址(第 18.6 节)。1.3 固定和可移动变量address-of 运算符(第 18.5.4 节)和 fixed 语句(第 18.6 节)将变量划分为两个类别:固定变量 (fixed variable) 和可移动变量 (moveable variable)。固定变量驻留在不受垃圾回收器的操作影响的存储位置中。(固定变量的示例包括局部变量、值参数和由取消指针引用而创建的变量。)另一方面,可移

15、动变量则驻留在会被垃圾回收器重定位或处置的存储位置中。(可移动变量的示例包括对象中的字段和数组的元素。)& 运算符(第 18.5.4 节)允许不受限制地获取固定变量的地址。但是,由于可移动变量会受到垃圾回收器的重定位或处置,因此可移动变量的地址只能使用 fixed 语句(第 18.6 节)获取,而且该地址只在此 fixed 语句的生存期内有效。准确地说,固定变量是下列之一: 用引用局部变量或值参数的 simple-name(第 7.5.2 节)表示的变量。 用 V.I 形式的 member-access(第 7.5.4 节)表示的变量,其中 V 是 struct-type 的固定变量。 用 *

16、P 形式的 pointer-indirection-expression(第 18.5.1 节)、P-I 形式的 pointer-member-access(第 18.5.2 节)或 PE 形式的 pointer-element-access(第 18.5.3 节)表示的变量。所有其他变量都属于可移动变量。请注意静态字段属于可移动变量。还请注意即使赋予 ref 或 out 形参的实参是固定变量,它们仍属于可移动变量。最后请注意,由取消指针引用而产生的变量总是属于固定变量。1.4 指针转换在不安全上下文中,可供使用的隐式转换的集合(第 6.1 节)也扩展为包括以下隐式指针转换: 从任何 poin

17、ter-type 到 void* 类型。 从 null 类型到任何 pointer-type。另外,在不安全上下文中,可供使用的显式转换的集合(第 6.2 节)也扩展为包括以下显式指针转换: 从任何 pointer-type 到任何其他 pointer-type。 从 sbyte、byte、short、ushort、int、uint、long 或 ulong 到任何 pointer-type。 从任何 pointer-type 到 sbyte、byte、short、ushort、int、uint、long 或 ulong。最后,在不安全上下文中,标准隐式转换的集合(第 6.3.1 节)包括以下

18、指针转换:两个指针类型之间的转换永远不会更改实际的指针值。换句话说,从一个指针类型到另一个指针类型的转换不会影响由指针给出的基础地址。当一个指针类型被转换为另一个指针类型时,如果没有将得到的指针正确地对指向的类型对齐,则当结果被取消引用时,该行为将是未定义的。一般情况下,“正确对齐”的概念是可传递的:如果指向类型 A 的指针正确地与指向类型 B 的指针对齐,而此指向类型 B 的指针又正确地与指向类型 C 的指针对齐,则指向类型 A 的指针将正确地与指向类型 C 的指针对齐。请考虑下列情况,其中具有一个类型的变量被通过指向一个不同类型的指针访问:char c = A;char* pc = &c;

19、void* pv = pc;int* pi = (int*)pv;int i = *pi; / undefined*pi = 123456;当一个指针类型被转换为指向字节的指针时,转换后的指针将指向原来所指变量的地址中的最低寻址字节。连续增加该变换后的指针(最大可达到该变量所占内存空间的大小),将产生指向该变量的其他字节的指针。例如,下列方法将 double 型变量中的八个字节的每一个显示为一个十六进制值: unsafe static void Main() double d = 123.456e23; byte* pb = (byte*)&d; for (int i = 0; sizeof(

20、double); +i) Console.Write(0:X2 , *pb+); Console.WriteLine();当然,产生的输出取决于字节存储顺序 (Endianness)。指针和整数之间的映射由实现定义。但是,在具有线性地址空间的 32 位和 64 位 CPU 体系结构上,指针和整型之间的转换通常与 uint 或 ulong 类型的值与这些整型之间的对应方向上的转换具有完全相同的行为。1.5 表达式中的指针在不安全上下文中,表达式可能产生指针类型的结果,但是在不安全上下文以外,表达式为指针类型属于编译时错误。准确地说,在不安全上下文以外,如果任何 simple-name(第 7.5

21、.2 节)、member-access(第 7.5.4 节)、invocation-expression(第 7.5.5 节)或 element-access(第 7.5.6 节)属于指针类型,则将发生编译时错误。在不安全上下文中,primary-no-array-creation-expression(第 7.5 节)和 unary-expression(第 7.6 节)产生式允许使用下列附加构造:primary-no-array-creation-expression:pointer-member-accesspointer-element-accesssizeof-expressionu

22、nary-expression:pointer-indirection-expressionaddressof-expression以下几节对这些构造进行了描述。相关的语法暗示了不安全运算符的优先级和结合性。1.5.1 指针间接寻址pointer-indirection-expression 包含一个星号 (*),后跟一个 unary-expression。pointer-indirection-expression:* unary-expression一元 * 运算符表示指针间接寻址并且用于获取指针所指向的变量。计算 *P 得到的结果(其中 P 为指针类型 T* 的表达式)是类型为 T 的一

23、个变量。将一元 * 运算符应用于 void* 类型的表达式或者应用于不是指针类型的表达式属于编译时错误。将一元 * 运算符应用于 null 指针的效果是由实现定义的。具体而言,不能保证此操作会引发 System.NullReferenceException。如果已经将无效值赋给指针,则一元 * 运算符的行为是未定义的。通过一元 * 运算符取消指针引用有时会产生无效值,这些无效值包括:没能按所指向的类型正确对齐的地址(请参见第 18.4 节中的示例)和超过生存期的变量的地址。出于明确赋值分析的目的,通过计算 *P 形式的表达式产生的变量被认为是初始化赋过值的(第 5.3.1 节)。1.5.2 指

24、针成员访问pointer-member-access 包含一个 primary-expression,后跟一个“-”标记,最后是一个 identifier。pointer-member-access:primary-expression - identifier在 P-I 形式的指针成员访问中,P 必须是除 void* 以外的某个指针类型的表达式,而 I 必须表示 P 所指向的类型的可访问成员。P-I 形式的指针成员访问的计算方式与 (*P).I 完全相同。有关指针间接寻址运算符 (*) 的说明,请参见第 18.5.1 节。有关成员访问运算符 (.) 的说明,请参见第 7.5.4 节。stru

25、ct Point public int x; public int y; public override string ToString() return ( + x + , + y + ) Point point; Point* p = &point; p-x = 10;y = 20; Console.WriteLine(p-ToString();- 运算符用于通过指针访问结构中的字段和调用结构中的方法。由于 P-I 操作完全等效于 (*P).I,因此 Main 方法可以等效地编写为: (*p).x = 10; (*p).y = 20; Console.WriteLine(*p).ToString();1.5.3 指针元素访问pointer-element-access 包括一个 primary-no-array-creation-expression,后跟一个用“”和“”括起来的表达式。pointer-element-access:primary-no-array-creation-expressi

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1