指针间接检查无效内存访问和分段错误
struct A { int i; };
...
A *p = (A*) (8); // or A *p = 0;
p->i = 5; // Undefined Behavior according C/C++ standard
然而,实际上大多数系统都会因此类代码而崩溃(分段错误)。
这是否意味着所有此类架构/系统都对指针间接进行隐藏检查(即p->
)来验证它是否访问了错误的内存位置?
如果是,那么这意味着即使在完美工作的代码中,我们也要为额外检查付出代价,对吗?
struct A { int i; };
...
A *p = (A*) (8); // or A *p = 0;
p->i = 5; // Undefined Behavior according C/C++ standard
However, practically most of the system would crash (segmentation fault) for such code.
Does it mean that all such Architectures/Systems have a hidden check for pointer indirection (i.e. p->
) to verify if it's accessing a wrong memory location ?
If yes, then it implies that even in perfectly working code we are paying the price for that extra check, correct ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
一般没有额外的隐藏检查,这只是使用虚拟内存的效果。
一些潜在的虚拟地址只是没有映射到物理内存,因此像 8 这样的转换可能会失败。
There are generally no extra hidden checks, this is just an effect of using virtual memory.
Some of the potential virtual addresses are just not mapped to physical memory, so translating things like 8 will likely fail.
是的,您正在为那张额外的支票付出代价。它不仅适用于指针间接寻址,还适用于任何内存访问(DMA 除外)。然而,检查的成本非常小。
当您的进程运行时,页表不会经常更改。部分页表将缓存在转换后备缓冲区中,访问缓冲区中包含条目的页面不会产生额外的损失。
如果您的进程访问没有 TLB 条目的页面,则 CPU 必须进行额外的内存访问以获取该页面的页表条目。然后它将被缓存。
您可以通过编写测试程序来查看其实际效果。为您的测试程序提供一大块内存,并开始随机读取和写入内存中的位置。使用命令行参数来更改大小。
如果您的操作系统允许“大页面”,则 TLB 可能确实能够覆盖非常大的地址空间。也许您可以通过从
mmap
分配 4k 块来破坏操作系统,在这种情况下,仅几兆工作集就可能会感觉到 TLB 未命中,具体取决于您的处理器。但是: 性能的小幅下降必须与虚拟内存的好处进行权衡,虚拟内存的好处太多,无法在此列出。
Yes, you are paying the price for that extra check. It's not just for pointer indirection, but any memory access (other than, say, DMA). However, the cost of the check is very small.
While your process is running, the page table does not change very often. Parts of the page table will be cached in the translation lookaside buffer, accessing pages with entries in the buffer incur no additional penalty.
If your process accesses a page without a TLB entry, then the CPU must make an additional memory access to fetch the page table entry for that page. It will then be cached.
You can see the effect of this in action by writing a test program. Give your test program a big chunk of memory and start randomly reading and writing locations in memory. Use a command line parameter to change the size.
If your operating system allows "big pages", the TLB might be able to cover a very large address space indeed. Perhaps you can sabotage the OS by allocating 4k chunks from
mmap
, in which case the TLB misses might be felt with only a few megs of working set, depending on your processor.However: The small performance drop must be weighed against the benefits of virtual memory, which are too numerous to list here.
不,不正确。出于两个原因,对有效内存访问绝对需要进行完全相同的检查:
1)否则,系统如何知道您正在访问什么物理内存以及该页面是否已经驻留?
2)否则,如果物理内存变得紧张,操作系统如何知道要调出哪些物理内存页?
它被集成到整个虚拟内存系统中,也是现代计算机表现出色的一部分。良好。它不是任何类型的单独检查,它是确定操作正在访问物理内存页面的过程的一部分。这是写时复制工作的一部分。 (同样的检查会检测何时需要副本。)
No, not correct. Those exact same checks are absolutely needed on valid memory accesses for two reasons:
1) Otherwise, how would the system know what physical memory you were accessing and whether the page was already resident?
2) Otherwise, how would the operating system know which pages of physical memory to page out if physical memory became tight?
It's integrated into the entire virtual memory system and part of what makes modern computers perform so amazingly well. It's not any kind of separate check, it's part of the process that determines which page of physical memory the operation is accessing. It's part of what makes copy-on-write work. (The very same check detects when a copy is needed.)
分段错误是指尝试访问 CPU 无法物理寻址的内存。当硬件通知操作系统有关内存访问冲突时,就会发生这种情况。因此,我认为没有额外的检查,如果尝试访问内存位置失败,硬件会通知操作系统,然后操作系统向导致异常的进程发送信号。默认情况下,接收信号的进程会转储核心并终止。
A segmentation fault is an attempt to access memory that the CPU cannot physically address. It occurs when the hardware notifies an operating system about a memory access violation. So I think there is no extra check as such If an attempt to access the memory location fails the hardware notifies the OS which then then sends a signal to the process which caused the exception. By default, the process receiving the signal dumps core and terminates.
首先,您需要阅读并理解这一点: http://en.wikipedia.org/wiki /Virtual_memory#Page_tables
因此,通常发生的情况是,当进程尝试取消引用无效的虚拟内存位置时,操作系统会捕获 MMU(请参阅上面的链接)针对无效虚拟地址引发的页错误异常(0x0、0x8,等等)。然后,操作系统在其页表中查找该地址,没有找到它,并向进程发出 SIGSEGV 信号(或类似信号),导致进程崩溃。
有效地址和无效地址之间的区别在于操作系统是否为该地址范围分配了页面。大多数操作系统被设计为从不分配第一页(从 0x0 开始的页),因此 NULL 取消引用总是会崩溃。
因此,您所说的“额外检查”实际上与每个页面错误发生的检查相同,无论地址是否有效 - 这只是页表查找是否成功的问题。
First of all, you need to read and understand this: http://en.wikipedia.org/wiki/Virtual_memory#Page_tables
So what typically happens is, when a process attempts to dereference an invalid virtual memory location, the OS catches the page fault exception raised by the MMU (see link above) for the invalid virtual address (0x0, 0x8, whatever). The OS then looks up the address in its page table, doesn't find it, and issues a SIGSEGV signal (or similar) to the process which causes the process to crash.
The difference between a valid and invalid address is whether the OS has allocated a page for that address range. Most OSes are designed to never allocate the first page (the one starting at 0x0) so that NULL dereferences will always crash.
So what you're calling an "extra check" is really the same check that occurs for every single page fault, valid address or not -- it's just a matter of whether the page table lookup succeeds.