C#中的不安全代码会导致内存损坏吗?

时间:2013-08-21 19:43:48

标签: c# .net

基本上,内存损坏是由覆盖您不应覆盖的内存引起的。我想知道这是否可能与C#中的不安全代码(即不通过调用外部非托管代码)。我看到两种可能的情况:

  • 访问空指针 - >陷入CLR,抛出一个 NullReferenceException
  • 访问指向无效随机存储位置的指针 - > 被CLR捕获,抛出AccessViolationException

在这两种情况下,似乎运行时检测并防止潜在的内存损坏发生。因此,是否有可能使用不安全的代码来破坏C#中的内存?作为必然结果,从不安全的代码中捕获AccessViolationExceptions是否安全?

4 个答案:

答案 0 :(得分:11)

你错过了Big Bullet:

  • 访问内存,获取AccessViolationException。

非常常见,.NET程序中总是存在大量可写内存。包括将元素写入数组的末尾,它很少被炸弹。内存页面边界的内存保护是精细的,Windows上为4096字节。 .NET GC大大提升了这一点,代际堆段是VM的大好处。捕捉AVE是非常不明智的。

可以使用的一些代码:

class Program {
    static unsafe void Main(string[] args) {
        var arr = new byte[1];
        for (int fill = 0; fill < 2 * 1024 - 64; ++fill) {
            byte[] dummy = new byte[1024];
        }
        fixed (byte* p = &arr[0]) {
            for (int ix = 1; ; ++ix)
                p[ix] = 42;
        }
    }
}

超过大约1.5兆字节。

答案 1 :(得分:10)

  

访问指向无效随机存储位置的指针

如果是阅读,则是安全的。如果是写入,如果内存位置恰好有效,则不安全,但您没有拥有它。你将在随机存储位置上涂鸦。

  

作为必然结果,从不安全的代码中捕获AccessViolationExceptions是否安全?

不,因为该异常告诉您a)您有错误并且b)内存可能已损坏且无法修复。抓住它并尽快拆除这个过程。

答案 2 :(得分:7)

  

C#中的不安全代码会导致内存损坏吗?

答案是肯定的!,请考虑以下示例执行此操作

int a = 10;
int* p = &a;
*(p+54)= 444;

CLR可能会也可能不会陷入此问题。

  

并非所有通过坏指针进行的读取或写入都会导致访问冲突,因此访问冲突通常表示通过错误指针发生了多次读取或写入,并且该内存可能已损坏。

来自Accessviolationexception Documentation

答案 3 :(得分:2)

导致AccessViolationException的内存写入没有发生,它没有做任何事情。

但是:它试图写入错误的位置的事实是一个非常强烈的指示,表明之前可能存在无效的写入操作(因为您的代码是错误的),并且这些写入可能指向可写的位置但不应该被改变。