C# 编写不安全代码
2011-01-06 16:11
134 查看
MSDN:"尽管实际上对 C 或 C++ 中的每种指针类型构造,C# 都设置了与之对应的引用类型,但仍然会有一些场合需要访问指针类型。例如,当需要与基础操作系统进行交互、访问内存映射设备,或实现一些以时间为关键的算法时,若没有访问指针的手段,就不可能或者至少很难完成。为了满足这样的需求,C# 提供了编写不安全代码的能力。
在不安全代码中,可以声明和操作指针,可以在指针和整型之间执行转换,还可以获取变量的地址,等等。在某种意义上,编写不安全代码很像在 C# 程序中编写 C 代码。"
不安全代码必须用修饰符 unsafe 明确地标记。
这里所谓的编写"不安全代码",就是要跳出.net CLR的限制,自己进行地址分配和垃圾回收.在C++里面,我们定义一个简单的指针,至少要做三件事,1.给他分配内存,2.保证类型转换正确3将内存空间释放,而在.net环境里,CLR将程序员从这些事情里解放出来,用户不再需要直接手工地进行内存操作。但是有时候,比如调用windows底层函数,或是效率上的原因使我们需要自己去操作地址空间,本文主要是说明在c#里面指针的用法.
指针的使用、操作内存
1.& 和 *
c++里面,我们很熟悉这两个东西.在c#里面他们也一样可以用,只不过含有他们的代码如果不在unsafe 标记下,编译器将会将它拒之门外.当然如果条件编译参数没有/unsafe 也是无法编译通过的(如果用vs.net集成编译环境,则在项目属性页-代码生成节将"允许不安全代码块"设置成true).
&可以取得变量的地址,但是并不是所有的变量,托管类型,将无法取得其地址.c#里面,普通的值类型都是可以取得地址的,比如struct,int,long等,而class是无法取得其地址的,另外string是比较特殊的类型,虽然是值类型,但它也是受管的.这里插一下另一个运算符,sizeof,它也是仅可用于unsafe模式下.
看下面这段代码,里面简单的用到了*,&,sizeof,还有c#里很少见但c++里大家很熟的->:
//代码
using System;
using System.Runtime.InteropServices;
public unsafe class Memory
{
const int HEAP_ZERO_MEMORY = 0x00000008;//内存起始地址
//获得进程堆的句柄
[DllImport("kernel32")]
static extern int GetProcessHeap();
//内存分配
[DllImport("kernel32")]
static extern void* HeapAlloc(int hHeap, int flags, int size);
//内存释放
[DllImport("kernel32")]
static extern bool HeapFree(int hHeap, int flags, void* block);
static int ph = GetProcessHeap();//获得进程堆的句柄
private Memory() {}
public static void* Alloc(int size) //内存分配
{
void* result = HeapAlloc(ph, HEAP_ZERO_MEMORY, size);
if (result == null) throw new OutOfMemoryException();
return result;
}
public static void Free(void* block) //内存释放
{
if (!HeapFree(ph, 0, block)) throw new InvalidOperationException();
}
}
class Test
{
unsafe static void Main()
{
byte* buffer = (byte*)Memory.Alloc(256);
for (int i = 0; i < 256; i++)
buffer[i] = (byte)i;
for (int i = 0; i < 256; i++)
Console.WriteLine(buffer[i]);
Memory.Free(buffer);
Console.ReadLine();
}
}
在不安全代码中,可以声明和操作指针,可以在指针和整型之间执行转换,还可以获取变量的地址,等等。在某种意义上,编写不安全代码很像在 C# 程序中编写 C 代码。"
不安全代码必须用修饰符 unsafe 明确地标记。
这里所谓的编写"不安全代码",就是要跳出.net CLR的限制,自己进行地址分配和垃圾回收.在C++里面,我们定义一个简单的指针,至少要做三件事,1.给他分配内存,2.保证类型转换正确3将内存空间释放,而在.net环境里,CLR将程序员从这些事情里解放出来,用户不再需要直接手工地进行内存操作。但是有时候,比如调用windows底层函数,或是效率上的原因使我们需要自己去操作地址空间,本文主要是说明在c#里面指针的用法.
指针的使用、操作内存
1.& 和 *
c++里面,我们很熟悉这两个东西.在c#里面他们也一样可以用,只不过含有他们的代码如果不在unsafe 标记下,编译器将会将它拒之门外.当然如果条件编译参数没有/unsafe 也是无法编译通过的(如果用vs.net集成编译环境,则在项目属性页-代码生成节将"允许不安全代码块"设置成true).
&可以取得变量的地址,但是并不是所有的变量,托管类型,将无法取得其地址.c#里面,普通的值类型都是可以取得地址的,比如struct,int,long等,而class是无法取得其地址的,另外string是比较特殊的类型,虽然是值类型,但它也是受管的.这里插一下另一个运算符,sizeof,它也是仅可用于unsafe模式下.
看下面这段代码,里面简单的用到了*,&,sizeof,还有c#里很少见但c++里大家很熟的->:
//代码
using System;
using System.Runtime.InteropServices;
public unsafe class Memory
{
const int HEAP_ZERO_MEMORY = 0x00000008;//内存起始地址
//获得进程堆的句柄
[DllImport("kernel32")]
static extern int GetProcessHeap();
//内存分配
[DllImport("kernel32")]
static extern void* HeapAlloc(int hHeap, int flags, int size);
//内存释放
[DllImport("kernel32")]
static extern bool HeapFree(int hHeap, int flags, void* block);
static int ph = GetProcessHeap();//获得进程堆的句柄
private Memory() {}
public static void* Alloc(int size) //内存分配
{
void* result = HeapAlloc(ph, HEAP_ZERO_MEMORY, size);
if (result == null) throw new OutOfMemoryException();
return result;
}
public static void Free(void* block) //内存释放
{
if (!HeapFree(ph, 0, block)) throw new InvalidOperationException();
}
}
class Test
{
unsafe static void Main()
{
byte* buffer = (byte*)Memory.Alloc(256);
for (int i = 0; i < 256; i++)
buffer[i] = (byte)i;
for (int i = 0; i < 256; i++)
Console.WriteLine(buffer[i]);
Memory.Free(buffer);
Console.ReadLine();
}
}
相关文章推荐
- 编写高质量代码改善C#程序的157个建议[泛型集合、选择集合、集合的安全]
- 编写高质量代码改善C#程序的157个建议——建议114:MD5不再安全
- 使用C#编写不安全代码(翻译)
- C#编写不安全代码初探
- C#中不安全代码的编写和指针的应用
- C#编写不安全代码 和应用程序域
- 编写高质量代码改善C#程序的157个建议——建议22:确保集合的线程安全
- 编写高质量代码改善C#程序的157个建议[泛型集合、选择集合、集合的安全]
- 编写高质量代码改善C#程序的157个建议——建议117:使用SSL确保通信中的数据安全
- 编写高质量代码改善C#程序的157个建议[为泛型指定初始值、使用委托声明、使用Lambda替代方法和匿名方法]
- c#编写ssl socket 安全的套接字层传输
- C#编码简单性之语义篇(如何编写简短的C#代码,随时更新)
- C#中的快捷键,可以更方便的编写代码
- C#语言编写代码逻辑
- 编写高质量代码改善C#程序的157个建议——建议34:为泛型参数设定约束
- C#编码简单性之函数篇(如何编写简短的C#代码,随时更新)
- 编写高质量代码改善C#程序的157个建议[正确操作字符串、使用默认转型方法、却别对待强制转换与as和is]
- 编写高质量代码改善C#程序的157个建议——建议66:正确捕获多线程中的异常
- 编写安全无错C代码