C#中使用不安全代码(使用指针的代码).doc_第1页
C#中使用不安全代码(使用指针的代码).doc_第2页
C#中使用不安全代码(使用指针的代码).doc_第3页
C#中使用不安全代码(使用指针的代码).doc_第4页
C#中使用不安全代码(使用指针的代码).doc_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

如何在 C# 中使用不安全代码(使用指针的代码)在C#中很少需要使用指针,但仍有一些需要使用的情况。例如,在下列情况中使用允许采用指针的不安全上下文是正确的:处理磁盘上的现有结构涉及内部包含指针的结构的高级COM或平台调用方案性能关键代码不鼓励在其他情况下使用不安全上下文。具体地说,不应该使用不安全上下文尝试在C#中编写C代码。警告使用不安全上下文编写的代码无法被验证为安全的,因此只有在代码完全受信任时才会执行该代码。换句话说,不可以在不受信任的环境中执行不安全代码。例如,不能从Internet上直接运行不安全代码。该教程包括下列示例:示例1使用指针复制一个字节数组。示例2显示如何调用WindowsReadFile函数。示例3显示如何打印可执行文件的Win32版本。示例1以下示例使用指针将一个字节数组从src复制到dst。用/unsafe选项编译此示例。/fastcopy.cs/compilewith:/unsafeusingSystem;classTest / Theunsafekeywordallowspointerstobeusedwithinthe / followingmethod:staticunsafevoidCopy(bytesrc,intsrcIndex,bytedst,intdstIndex,intcount)if(src=null|srcIndex0|dst=null|dstIndex0|count0)thrownewArgumentException();intsrcLen=src.Length;intdstLen=dst.Length;if(srcLen-srcIndexcount|dstLen-dstIndexcount)thrownewArgumentException();/Thefollowingfixedstatementpinsthelocationof thesrcanddst/objectsinmemorysothattheywill/notbemovedbygarbagecollection.fixed(byte*pSrc=src,pDst=dst)byte*ps=pSrc;byte*pd=pDst;/Loopoverthecountinblocksof4bytes,copyingan/integer(4bytes)atatime:for(intn=0;ncount/4;n+)*(int*)pd)=*(int*)ps);pd+=4;ps+=4;/Completethecopybymovinganybytesthatwerent/movedinblocksof4:for(intn=0;ncount%4;n+)*pd=*ps;pd+;ps+;staticvoidMain(stringargs)bytea=newbyte100;byteb=newbyte100;for(inti=0;i100;+i)ai=(byte)i;Copy(a,0,b,0,100);Console.WriteLine(Thefirst10elementsare:);for(inti=0;i10;+i)Console.Write(bi+);Console.WriteLine(n);输出示例Thefirst10elementsare:0123456789代码讨论请注意使用了unsafe关键字,这允许在Copy方法内使用指针。fixed语句用于声明指向源和目标数组的指针。它锁定src和dst对象在内存中的位置以便使其不会被垃圾回收移动。当fixed块完成后,这些对象将被解除锁定。通过略过数组界限检查,不安全代码可提高性能。示例2本示例显示如何从Platform.SDK调用WindowsReadFile函数,这要求使用不安全上下文,因为读缓冲区需要将指针作为参数。/readfile.cs/compilewith:/unsafe/arguments:readfile.cs/Usetheprogramtoreadanddisplayatextfile.usingSystem;usingSystem.Runtime.InteropServices;usingSystem.Text;classFileReaderconstuintGENERIC_READ=0x80000000;constuintOPEN_EXISTING=3;IntPtrhandle;DllImport(kernel32,SetLastError=true)staticexternunsafeIntPtrCreateFile(stringFileName,/filenameuintDesiredAccess,/accessmodeuintShareMode,/sharemodeuintSecurityAttributes,/SecurityAttributesuintCreationDisposition,/howtocreateuintFlagsAndAttributes,/fileattributesinthTemplateFile);/handletotemplatefileDllImport(kernel32,SetLastError=true)staticexternunsafeboolReadFile(IntPtrhFile,/handletofilevoid*pBuffer,/databufferintNumberOfBytesToRead,/numberofbytestoreadint*pNumberOfBytesRead,/numberofbytesreadintOverlapped);/overlappedbufferDllImport(kernel32,SetLastError=true)staticexternunsafeboolCloseHandle(IntPtrhObject);/handletoobjectpublicboolOpen(stringFileName)/opentheexistingfileforreadinghandle=CreateFile(FileName,GENERIC_READ,0,0,OPEN_EXISTING,0,0);if(handle!=IntPtr.Zero)returntrue;elsereturnfalse;publicunsafeintRead(bytebuffer,intindex,intcount)intn=0;fixed(byte*p=buffer)if(!ReadFile(handle,p+index,count,&n,0)return0;returnn;publicboolClose()/closefilehandlereturnCloseHandle(handle);classTestpublicstaticintMain(stringargs)if(args.Length!=1)Console.WriteLine(Usage:ReadFile);return1;if(!System.IO.File.Exists(args0)Console.WriteLine(File+args0+notfound.);return1;bytebuffer=newbyte128;FileReaderfr=newFileReader();if(fr.Open(args0)/AssumethatanASCIIfileisbeingreadASCIIEncodingEncoding=newASCIIEncoding();intbytesRead;dobytesRead=fr.Read(buffer,0,buffer.Length);stringcontent=Encoding.GetString(buffer,0,bytesRead);Console.Write(0,content);while(bytesRead0);fr.Close();return0;elseConsole.WriteLine(Failedtoopenrequestedfile);return1;输入示例在编译和运行此示例时,下列来自readfile.txt的输入将产生在“输出示例”中显示的输出。line1line2输出示例line1line2代码讨论传递到Read函数的字节数组是托管类型。这意味着公共语言运行库垃圾回收器可能会随意地对数组使用的内存进行重新定位。fixed语句允许您获取指向字节数组使用的内存的指针,并且标记实例,以便垃圾回收器不会移动它。在fixed块的末尾,将标记该实例以便可以移动它。此功能称为声明式锁定。锁定的好处是系统开销非常小,除非在fixed块中发生垃圾回收(但此情况不太可能发生)。示例3本示例读取并显示可执行文件的Win32版本号,在本示例中此版本号与程序集版本号相同。本例中使用的可执行文件为printversion.exe。本示例使用Platform.SDK函数VerQueryValue、GetFileVersionInfoSize和GetFileVersionInfo从指定的版本信息资源中检索指定的版本信息。本示例使用了指针,因为它可以简化在其签名中使用指向指针的指针(这在Win32API中很常见)的方法的使用。/printversion.cs/compilewith:/unsafeusingSystem;usingSystem.Reflection;usingSystem.Runtime.InteropServices;/Givethisassemblyaversionnumber:assembly:AssemblyVersion()publicclassWin32ImportsDllImport(version.dll)publicstaticexternboolGetFileVersionInfo(stringsFileName,inthandle,intsize,byteinfoBuffer);DllImport(version.dll)publicstaticexternintGetFileVersionInfoSize(stringsFileName,outinthandle);/Thethirdparameter-outstringpValue-isautomatically/marshaledfromANSItoUnicode:DllImport(version.dll)unsafepublicstaticexternboolVerQueryValue(bytepBlock,stringpSubBlock,outstringpValue,outuintlen);/ThisVerQueryValueoverloadismarkedwithunsafebecause/itusesashort*:DllImport(version.dll)unsafepublicstaticexternboolVerQueryValue(bytepBlock,stringpSubBlock,outshort*pValue,outuintlen);publicclassC/Mainismarkedwithunsafebecauseitusespointers:unsafepublicstaticintMain()tryinthandle=0;/Figureouthowmuchversioninfothereis:intsize=Win32Imports.GetFileVersionInfoSize(printversion.exe,outhandle);if(size=0)return-1;bytebuffer=newbytesize;if(!Win32Imports.GetFileVersionInfo(printversion.exe,handle,size,buffer)Console.WriteLine(Failedtoqueryfileversioninfo.);return1;short*subBlock=null;uintlen=0;/Getthelocaleinfofromtheversioninfo:if(!Win32Imports.VerQueryValue(buffer,VarFileInfoTranslation,outsubBlock,outlen)Console.WriteLine(Failedtoqueryversioninformation.);return1;stringspv=StringFileInfo+subBlock0.ToString(X4)+subBlock1.ToString(X4)+ProductVersion;byte*pVersion=null;/GettheProductVersionvalueforthisprogram:stringversionInf

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论