为什么不*为(int *)= 0会导致访问冲突? [英] Why doesn't *(int*)0=0 cause an access violation?

查看:203
本文介绍了为什么不*为(int *)= 0会导致访问冲突?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有关教育目的,我写了一组在C#中导致运行时异常,以了解所有的例外是和什么原因导致它们的方法。现在,我正与能够引起 AccessViolationException

For educational purposes, I'm writing a set of methods that cause runtime exceptions in C# to understand what all the exceptions are and what causes them. Right now, I'm tinkering with programs that cause an AccessViolationException.

最明显的方法(对我来说)修补程序要做到这一点是写一个受保护的内存位置,如:

The most obvious way (to me) to do this was to write to a protected memory location, like this:

System.Runtime.InteropServices.Marshal.WriteInt32(IntPtr.Zero, 0);

正如我所希望的,这引发了 AccessViolationException 。我想要做的更简洁,所以我决定写不安全的代码的程序,并通过指定 0 零做(我认为是)完全一样的东西。终场

Just as I had hoped, this threw an AccessViolationException. I wanted to do it more concisely, so I decided to write a program with unsafe code, and do (what I thought was) exactly the same thing by assigning 0 to the zero-pointer.

unsafe
{
    *(int*)0 = 0;
}



对于躲避我的原因,这将引发一个的NullReferenceException 。我与它的一些发挥了一圈,发现了,使用 *为(int *)1 ,而不是还抛出一个的NullReferenceException ,但如果你用一个负数,比如 *(INT *) - 1 会抛出 AccessViolationException

For reasons that elude me, this throws a NullReferenceException. I played around with it some and found out that using *(int*)1 instead also throws a NullReferenceException, but if you use a negative number, like *(int*)-1 it will throw an AccessViolationException.

这是怎么回事?为什么 *为(int *)= 0 引起的NullReferenceException ,以及为何它没有引起 AccessViolationException

What's going on here? Why does *(int*)0 = 0 cause a NullReferenceException, and why doesn't it cause an AccessViolationException?

推荐答案

一个空引用异常发生在你提领一空指针?;在CLR不关心空指针是否是不安全的,终场前还插着它还是一个托管指针(即参考,引用类型的对象)零陷了进去整数零。

A null reference exception happens when you dereference a null pointer; the CLR does not care whether the null pointer is an unsafe pointer with the integer zero stuck into it or a managed pointer (that is, a reference to an object of reference type) with zero stuck into it.

如何在CLR知道空已取消引用?又是如何在CLR知道,当其他一些无效的指针已经解除引用?每个指针指向在这个过程中的虚拟存储器地址空间某处虚拟存储器的一个页。操作系统跟踪哪些网页是有效的和它们是无效的;当你触摸一个无效页它提出这是由CLR检测到异常。在CLR那么表面,作为任何一个无效的访问异常或一个空引用异常。

How does the CLR know that null has been dereferenced? And how does the CLR know when some other invalid pointer has been dereferenced? Every pointer points to somewhere in a page of virtual memory in the virtual memory address space of the process. The operating system keeps track of which pages are valid and which are invalid; when you touch an invalid page it raises an exception which is detected by the CLR. The CLR then surfaces that as either an invalid access exception or a null reference exception.

如果无效访问到内存的底部64K,这是一个空裁判例外。 ,否则是无效的访问异常

If the invalid access is to the bottom 64K of memory, it's a null ref exception. Otherwise it is an invalid access exception.

这解释了为什么提领零和一给空REF例外,为什么提领-1给出了一个无效的访问除外; -1 0xFFFFFFFF的指针在32位机器上,并且特定页面(在x86机器上)总是留给操作系统用于其自己的目的。用户代码不能访问它。

This explains why dereferencing zero and one give a null ref exception, and why dereferencing -1 gives an invalid access exception; -1 is pointer 0xFFFFFFFF on 32 bit machines, and that particular page (on x86 machines) is always reserved for the operating system to use for its own purposes. User code cannot access it.

现在,你可能会问,为什么不只是做的空引用异常的指针为零,无效的访问异常的一切?因为多数时候少量取消引用的时候,那是因为你通过一个空引用了它。试想一下,比如你试图做的:

Now, you might reasonably ask why not just do the null reference exception for pointer zero, and invalid access exception for everything else? Because the majority of the time when a small number is dereferenced, it is because you got to it via a null reference. Imagine for example that you tried to do:

int* p = (int*)0;
int x = p[1];



编译器把该进的道德等价的:

The compiler translates that into the moral equivalent of:

int* p = (int*)0;
int x = *( (int*)((int)p + 1 * sizeof(int)));



这是提领4.但是,从用户的角度来看, P [1] 肯定看起来像空的提领!所以这是报告的错误。

which is dereferencing 4. But from the user's perspective, p[1] surely looks like a dereference of null! So that is the error that is reported.

这篇关于为什么不*为(int *)= 0会导致访问冲突?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆