跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
C Sharp 不安全代码
”︁
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
= C#不安全代码 = == 介绍 == '''不安全代码'''是C#中一种允许直接操作内存和指针的特殊功能,它绕过了CLR(公共语言运行时)的内存安全检查机制。虽然C#通常强调类型安全和内存安全,但在某些高性能或与底层系统交互的场景中,开发者可能需要使用指针来直接访问内存。不安全代码通过<code>unsafe</code>关键字启用,并允许在特定代码块中使用指针和其他低级操作。 不安全代码的典型应用包括: * 高性能计算(如数学算法优化) * 与原生代码或硬件交互(如调用C/C++库) * 处理内存映射文件或网络协议 == 启用不安全代码 == 在C#项目中使用不安全代码需要: 1. 在代码中使用<code>unsafe</code>关键字标记代码块 2. 在项目配置中启用"Allow Unsafe Code"选项(在Visual Studio中可通过项目属性 > 生成设置启用) 示例项目配置(.csproj文件): <syntaxhighlight lang="xml"> <PropertyGroup> <AllowUnsafeBlocks>true</AllowUnsafeBlocks> </PropertyGroup> </syntaxhighlight> == 基本语法 == === unsafe关键字 === <code>unsafe</code>可以修饰: * 整个方法 * 代码块 * 类或结构体 示例: <syntaxhighlight lang="csharp"> unsafe void PointerMethod() { int x = 10; int* ptr = &x; // 获取x的内存地址 Console.WriteLine($"Value: {*ptr}"); // 解引用指针 } </syntaxhighlight> 输出: <pre> Value: 10 </pre> === 指针类型 === C#中的指针类型通过在类型后添加<code>*</code>表示: * <code>int*</code> - 整型指针 * <code>double*</code> - 双精度浮点指针 * <code>char*</code> - 字符指针 指针操作符: * <code>&</code> - 取地址运算符 * <code>*</code> - 解引用运算符 * <code>-></code> - 通过指针访问成员(相当于<code>(*ptr).member</code>) == 指针操作示例 == === 基本指针操作 === <syntaxhighlight lang="csharp"> unsafe { int number = 42; int* pointer = &number; Console.WriteLine($"Address: {(long)pointer:X}"); // 输出内存地址(16进制) Console.WriteLine($"Value: {*pointer}"); // 输出存储的值 *pointer = 100; // 通过指针修改值 Console.WriteLine($"New value: {number}"); } </syntaxhighlight> 输出: <pre> Address: 2BF4A3D84FC Value: 42 New value: 100 </pre> === 指针算术 === 指针支持加减运算来移动内存位置(按类型大小移动): <syntaxhighlight lang="csharp"> unsafe { int[] numbers = { 10, 20, 30, 40, 50 }; fixed (int* ptr = numbers) { for (int i = 0; i < 5; i++) { Console.WriteLine($"Address: {(long)(ptr + i):X}, Value: {*(ptr + i)}"); } } } </syntaxhighlight> 输出: <pre> Address: 2BF4A3D84FC, Value: 10 Address: 2BF4A3D8500, Value: 20 Address: 2BF4A3D8504, Value: 30 Address: 2BF4A3D8508, Value: 40 Address: 2BF4A3D850C, Value: 50 </pre> 注意:数组访问必须使用<code>fixed</code>语句防止垃圾回收移动内存。 == 实际应用案例 == === 图像处理 === 不安全代码常用于高性能图像处理,如快速像素操作: <syntaxhighlight lang="csharp"> unsafe void InvertImage(Bitmap bitmap) { BitmapData data = bitmap.LockBits( new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat); byte* ptr = (byte*)data.Scan0; int bytesPerPixel = Image.GetPixelFormatSize(bitmap.PixelFormat) / 8; int totalBytes = data.Stride * data.Height; for (int i = 0; i < totalBytes; i += bytesPerPixel) { ptr[i] = (byte)(255 - ptr[i]); // B ptr[i+1] = (byte)(255 - ptr[i+1]); // G ptr[i+2] = (byte)(255 - ptr[i+2]); // R } bitmap.UnlockBits(data); } </syntaxhighlight> === 与原生代码交互 === 调用Windows API函数示例: <syntaxhighlight lang="csharp"> [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] public static extern unsafe int MultiByteToWideChar( uint codePage, uint flags, byte* multiByteStr, int multiByteLength, char* wideCharStr, int wideCharLength); unsafe string ConvertToUnicode(byte[] multiByte) { fixed (byte* mbPtr = multiByte) { int length = MultiByteToWideChar(0, 0, mbPtr, -1, null, 0); char[] wideChars = new char[length]; fixed (char* wcPtr = wideChars) { MultiByteToWideChar(0, 0, mbPtr, -1, wcPtr, length); } return new string(wideChars, 0, length - 1); } } </syntaxhighlight> == 内存布局与结构体 == 使用<code>StructLayout</code>控制内存布局: <syntaxhighlight lang="csharp"> [StructLayout(LayoutKind.Explicit)] unsafe struct Packet { [FieldOffset(0)] public uint Header; [FieldOffset(4)] public fixed byte Data[256]; [FieldOffset(260)] public ushort Checksum; } </syntaxhighlight> == 安全注意事项 == 使用不安全代码时需特别注意: 1. '''内存安全''':指针操作可能造成内存泄漏或损坏 2. '''类型安全''':错误的指针类型转换会导致未定义行为 3. '''固定对象''':使用<code>fixed</code>防止垃圾回收移动内存 4. '''缓冲区溢出''':指针算术可能导致数组越界 == 性能考虑 == <mermaid> pie title 不安全代码适用场景 "性能关键代码" : 45 "原生代码交互" : 30 "特殊内存操作" : 20 "其他" : 5 </mermaid> 数学公式示例(指针地址计算): <math> address_{new} = address_{base} + (index \times sizeof(T)) </math> 其中: * <math>address_{base}</math>是基地址 * <math>index</math>是元素索引 * <math>sizeof(T)</math>是类型T的大小 == 总结 == C#不安全代码提供了直接内存访问能力,在特定场景下非常有用,但应谨慎使用。关键点: * 使用<code>unsafe</code>关键字启用不安全上下文 * 指针操作允许直接内存访问但牺牲安全性 * <code>fixed</code>语句防止垃圾回收移动托管对象 * 不安全代码主要用于性能优化和与原生代码交互 建议开发者在确实需要时才使用不安全代码,并确保充分测试相关代码。 [[Category:编程语言]] [[Category:C Sharp]] [[Category:C Sharp 高级主题]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)