如何触发访问冲突异常

Lio*_*gan 7 c++ windows compiler-construction cpu visual-c++

有时错误可能导致内存访问冲突异常.

这个异常究竟是如何触发的?幕后有什么机制?

它是否需要来自CPU(从哪个CPU开始?)/从OS(从什么版本开始?)/从编译器(从什么版本开始?)的支持

编辑:

我想要更好地理解的一个特定场景:

以下代码可能会导致访问冲突异常.

TCHAR* czXXX= _T("ABCDEFG");
czXXX[0]= 'A';
Run Code Online (Sandbox Code Playgroud)

我猜czXXX指向一个只读内存块,但究竟发生了什么?

sar*_*old 11

内存访问违规是一个很大的话题:)

计算机系统中的信息保护(自1973年开始:)奠定了一种分段机制,其中进程被分配了一个基础和一个边界 ; 任何尝试访问范围之外的内存base:base+bound意味着该程序已经做了一些愚蠢的事情,应该被杀死.

80x86系列处理器实现了基本的段支持,GEMSOS安全内核是基于此机制的A1认证操作系统内核.

但是段不是非常动态的,几乎所有现代操作系统都是分页系统,当它不可用时会内存中分页.这依赖于具有MMU(内存管理单元)的CPU ,其检查所有存储器访问以获得正确的特权以及是否存在正确的存储器映射.当进程尝试访问当前未映射到RAM的内存时,MMU向CPU发出已发生故障的信号,并且CPU暂停进程以从磁盘加载请求的内存页.(或者,如果内存不应该为进程映射,比如它尝试访问0x0或者某些未映射的随机内存位置mmap或类似的内存分配原语,则会终止进程.)

英特尔的80386是第一个英特尔芯片,支持分页,这就是为什么Windows 3.1中的"386 Enchanced模式"是这么多比286更好的模式.

编译器并没有真正参与其中,但CPU,MMU和操作系统内核必须协同工作.


Eli*_*ser 6

在x86架构(以及大多数其他架构)中,这是从MMU(内存管理单元)开始的.MMU用于将虚拟内存地址转换为物理内存地址.如果请求访问无效地址(0x00000000或太高),MMU将陷阱(中断)到操作系统(实际上这是针对不在TLB中的每次访问完成的(Translate Lookaside Buffer - MMU转换)缓存")).操作系统将能够判断这是非法的内存访问,并通过依赖于操作系统的机制传播到用户应用程序(Linux(SIGSEGV)中的信号,我对Windows不熟悉,足以说明它是如何完成的)在里面).

此功能适用于任何现代CPU,OS和编译器.最基本的要求是MMU,它存在于除最基本的嵌入式CPU之外的所有CPU中.我怀疑目前有任何不支持此操作的PC.

编辑:

在OP编辑之后,当使用文字字符串时,内存将放在可执行文件的.text段中.这是二进制代码和常量值所在的位置.当然,在大多数操作系统中,这是只读的(特别是在具有各种安全增强功能的Linux下).当您尝试更改文字字符串的值时,您基本上是在尝试写入只读内存,从而导致访问冲突.同样,这被MMU捕获,该MMU看到对只读存储器地址的写命令.

  • 依赖于操作系统的机制在 Windows 中被称为“结构化异常”:http://msdn.microsoft.com/en-us/library/ms680657%28v=vs.85%29.aspx (2认同)