Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-apps-script/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#中的不安全代码会导致内存损坏吗?_C#_.net - Fatal编程技术网

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

C#中的不安全代码会导致内存损坏吗?,c#,.net,C#,.net,基本上,内存损坏是由覆盖不应该覆盖的内存引起的。我想知道C#中的不安全代码是否可能实现这一点(即,不通过调用外部非托管代码)。我看到两种可能的情况: 访问CLR捕获的空指针->会抛出 NullReferenceException 访问指向无效随机内存位置的指针-> 被CLR捕获,引发AccessViolationException 在这两种情况下,运行时都会检测并防止潜在的内存损坏。因此,是否有可能使用不安全的代码破坏C#中的内存?作为推论,从不安全代码捕获AccessViolationEx

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

  • 访问CLR捕获的空指针->会抛出 NullReferenceException
  • 访问指向无效随机内存位置的指针-> 被CLR捕获,引发AccessViolationException
在这两种情况下,运行时都会检测并防止潜在的内存损坏。因此,是否有可能使用不安全的代码破坏C#中的内存?作为推论,从不安全代码捕获AccessViolationException安全吗

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


如果是读取,则是安全的。如果它是一个写操作,那么如果内存位置恰好是有效的,但不是您自己的,则是不安全的。您将在随机内存位置上涂鸦

作为推论,从不安全代码捕获AccessViolationException安全吗


不,因为该异常告诉您a)您有一个bug,b)内存可能已损坏,无法修复。捕获它并尽快中断进程。

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

但是:它试图写入错误的位置这一事实非常强烈地表明,以前可能有过无效的写入操作(因为您的代码有缺陷),并且这些写入操作可能指向可写入但不应更改的位置

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

答案是肯定的!,考虑下面的例子,

int a = 10;
int* p = &a;
*(p+54)= 444;
CLR可能会也可能不会捕捉到这一点

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


中,您错过了一个重要的要点:

  • 正在访问内存,而不是获取AccessViolationException
这是很常见的,在.NET程序中总是有很多可写内存。包括在数组末尾之外写入元素,它很少轰炸。内存保护在内存页边界上是细粒度的,在Windows上为4096字节。NETGC大大提高了这一点,各代堆段都是虚拟机的大块头。捕捉鸟类是非常不明智的

要使用的一些代码:

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;
        }
    }
}
类程序{
静态不安全void Main(字符串[]args){
var arr=新字节[1];
对于(int-fill=0;fill<2*1024-64;++fill){
字节[]伪=新字节[1024];
}
已修复(字节*p=&arr[0]){
对于(int-ix=1;;++ix)
p[ix]=42;
}
}
}

超出约1.5兆字节。

“如果是写操作,则如果内存位置恰好有效,但不是您自己的,则是不安全的。”如果超出了应用程序的边界,Windows将终止您的进程,好吗。@Renan如果您没有处理此异常,是的。我不太明白,如果抛出AccessViolationException,为什么内存会损坏。抛出该异常的事实是否意味着CLR捕获了访问无效内存的尝试,因此不允许它发生?异常可能在发生静默损坏后抛出。此外,如果您跨越页面边界进行写操作,则可能会产生半写操作。即使您拥有内存位置,写操作也可能会损坏内容。不安全的代码可能会在托管对象、堆数据结构、堆栈帧等的顶部涂鸦。在C#中,它是一个NullReferenceExc选项。我怀疑clr是否会对托管和非托管空解引用引发相同的异常。修复,谢谢。是的,这是相同的异常,您可以自己轻松地尝试,即
var ptr=(int*)0*ptr=1;//抛出NullReferenceException
还要注意,在.net 4.0中,如果有损坏状态的指示,默认情况下进程将终止。您缺少第三种情况:访问指向包含您不能修改的数据的有效内存位置的指针。没有被CLR捕获,没有异常,会损坏内存。更一般地说,“不安全代码”功能被称为“不安全”,因为它不安全。CLR不能保证将您从错误中解救出来;这就是为什么它被称为“不安全”。