C#中的不安全代码会导致内存损坏吗?
基本上,内存损坏是由覆盖不应该覆盖的内存引起的。我想知道C#中的不安全代码是否可能实现这一点(即,不通过调用外部非托管代码)。我看到两种可能的情况:C#中的不安全代码会导致内存损坏吗?,c#,.net,C#,.net,基本上,内存损坏是由覆盖不应该覆盖的内存引起的。我想知道C#中的不安全代码是否可能实现这一点(即,不通过调用外部非托管代码)。我看到两种可能的情况: 访问CLR捕获的空指针->会抛出 NullReferenceException 访问指向无效随机内存位置的指针-> 被CLR捕获,引发AccessViolationException 在这两种情况下,运行时都会检测并防止潜在的内存损坏。因此,是否有可能使用不安全的代码破坏C#中的内存?作为推论,从不安全代码捕获AccessViolationEx
- 访问CLR捕获的空指针->会抛出 NullReferenceException
- 访问指向无效随机内存位置的指针-> 被CLR捕获,引发AccessViolationException
如果是读取,则是安全的。如果它是一个写操作,那么如果内存位置恰好是有效的,但不是您自己的,则是不安全的。您将在随机内存位置上涂鸦 作为推论,从不安全代码捕获AccessViolationException安全吗
不,因为该异常告诉您a)您有一个bug,b)内存可能已损坏,无法修复。捕获它并尽快中断进程。导致AccessViolationException的内存写入没有发生,它没有做任何事情 但是:它试图写入错误的位置这一事实非常强烈地表明,以前可能有过无效的写入操作(因为您的代码有缺陷),并且这些写入操作可能指向可写入但不应更改的位置 C#中的不安全代码会导致内存损坏吗 答案是肯定的!,考虑下面的例子,
int a = 10;
int* p = &a;
*(p+54)= 444;
CLR可能会也可能不会捕捉到这一点
并非所有通过坏指针进行的读取或写入都会导致访问冲突,因此访问冲突通常表示通过坏指针进行了多次读取或写入,并且内存可能已损坏
从中,您错过了一个重要的要点:
- 正在访问内存,而不是获取AccessViolationException
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不能保证将您从错误中解救出来;这就是为什么它被称为“不安全”。