C#内存管理:不安全的关键字和指针
在C#中使用不安全关键字使用指针会产生什么后果(正面/负面)?例如,垃圾收集会变成什么样子,性能的增益/损耗是什么,与其他语言相比,性能的增益/损耗是什么手动内存管理,危险是什么,在什么情况下使用这种语言功能真的是合理的,编译的时间长吗 引用《2008年专业杂志》: “使用 指针是:C#内存管理:不安全的关键字和指针,c#,memory-management,pointers,keyword,unsafe,C#,Memory Management,Pointers,Keyword,Unsafe,在C#中使用不安全关键字使用指针会产生什么后果(正面/负面)?例如,垃圾收集会变成什么样子,性能的增益/损耗是什么,与其他语言相比,性能的增益/损耗是什么手动内存管理,危险是什么,在什么情况下使用这种语言功能真的是合理的,编译的时间长吗 引用《2008年专业杂志》: “使用 指针是: 向后兼容性-尽管 .NET运行时仍然可以 调用本机Windows API函数,以及 对于某些操作,这可能是 完成任务的唯一方法。 这些API函数通常是 用C语言编写,通常需要 指针作为参数。但是,在 在许多情况下,
我可以给你一个值得使用的情况:
我必须逐像素生成位图<代码>绘图.位图.SetPixel()太慢了。因此,我构建了自己的位图数据的托管
数组
,并使用safe
获取IntPtr
。正如Conrad已经提到的,在某些情况下,不安全地访问C中的内存是有用的。它们没有那么多,但有一些:
- 使用
进行操作几乎是一个典型的例子,您需要通过使用Bitmap
不安全的
获得一些额外性能
- 与旧API(如WinAPI或本机C/C++DLL)的互操作性是另一个非常有用的领域,
——例如,您可能希望调用一个接受/返回非托管指针的函数unsafe
不安全的
(或者如果您使用的是没有不安全的VB.NET,那么这是一个选项)
积极后果:
因此,C#中存在的不安全
的主要积极后果是,您可以更轻松地编写一些代码(互操作性),也可以更高效地编写一些代码(使用位图或使用数组进行一些繁重的数值计算-尽管我不太确定第二个)
负面后果:当然,使用不安全
,您必须付出一定的代价:
- 不可验证代码:使用
不安全
功能编写的代码变得不可验证,这意味着您的代码可能以任何方式危害运行时。在完全信任的情况下(例如,不受限制的桌面应用程序),这不是一个大问题-你只是没有所有好的.NET CLR保证。但是,您不能在受限制的环境中运行应用程序,例如公共web托管、Silverlight或部分信任(例如,从网络运行的应用程序)
- 垃圾收集器在使用不安全的
时也需要小心。通常允许GC重新定位托管堆上的对象(以保持内存碎片整理)。当您获取指向某个对象的指针时,需要使用fixed
关键字告诉GC在您完成之前无法移动该对象(这可能会影响垃圾收集的性能,当然,这取决于具体的场景)
我猜想,如果C#不必与较旧的代码进行互操作,它可能不会支持不安全的(而像Singularity这样的研究项目试图创建基于托管语言的更可验证的操作系统,显然不允许使用usnsafe代码)。然而,在现实世界中,不安全
在某些(罕见的)情况下是有用的。垃圾收集对于长寿命对象来说效率很低。Net的垃圾收集器在大多数对象释放得相当快,并且一些对象“永远存在”的情况下工作得最好。问题是,寿命较长的对象只在完全垃圾收集期间释放,这会导致严重的性能损失。本质上,长寿物体很快进入第二代
(有关更多信息,您可能需要阅读.Net的分代垃圾收集器:)
在对象或内存使用将长期存在的情况下,手动内存管理将产生更好的性能,因为它可以释放到系统中,而不需要完全的垃圾收集
实现某种基于单个大字节数组、结构和大量指针算法的内存管理系统,理论上可以提高性能