为什么我的程序崩溃时,我写过去的数组的结束? [英] why doesn't my program crash when I write past the end of an array?

查看:97
本文介绍了为什么我的程序崩溃时,我写过去的数组的结束?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么低于code工作没有任何崩溃@运行?

Why the below code works without any crash @ runtime ?

和同样大小完全依赖于机器/平台/编译器!!我甚至可以在64位机器给高达200。怎么会在主要功能分割故障在操作系统中得到检测?

And also the size is completely dependent on machine/platform/compiler!!. I can even give upto 200 in a 64-bit machine. how would a segmentation fault in main function get detected in the OS?

void main(int argc, char* argv[])
{
    int arr[3];
    arr[4] = 99;
}

在哪里这个缓冲空间从何而来?就是这个堆栈中分配给进程?

Where does this buffer space come from? Is this the stack allocated to a process ?

推荐答案

东西我写了一段前教育的宗旨...

Something I wrote sometime ago for education-purposes...

考虑下面的C程序:

int q[200];

main(void) {
    int i;
    for(i=0;i<2000;i++) {
        q[i]=i;
    }
}

编译它,执行它后,一个核心转储产生:

after compiling it and executing it, a core dump is produced:

$ gcc -ggdb3 segfault.c
$ ulimit -c unlimited
$ ./a.out
Segmentation fault (core dumped)

现在用gdb进行验尸分析:

now using gdb to perform a post mortem analysis:

$ gdb -q ./a.out core
Program terminated with signal 11, Segmentation fault.
[New process 7221]
#0  0x080483b4 in main () at s.c:8
8       q[i]=i;
(gdb) p i
$1 = 1008
(gdb)

呵呵,当一个分配的200个项目外编写的程序并没有出现段错误,而不是坠毁当i = 1008,为什么?

huh, the program didn’t segfault when one wrote outside the 200 items allocated, instead it crashed when i=1008, why?

输入页面。

一个可以决定在UNIX / Linux几种方式页尺寸,一种方法是使用系统功能的sysconf()是这样的:

One can determine the page size in several ways on UNIX/Linux, one way is to use the system function sysconf() like this:

#include <stdio.h>
#include <unistd.h> // sysconf(3)

int main(void) {
    printf("The page size for this system is %ld bytes.\n",
            sysconf(_SC_PAGESIZE));

    return 0;
}

这给输出:

该系统的页面大小为4096字节。

The page size for this system is 4096 bytes.

或者一个可以使用命令行工具在getconf是这样的:

or one can use the commandline utility getconf like this:

$ getconf PAGESIZE
4096

验尸

原来,该段错误在我= 200未出现,但在我= 1008,让我们找出原因。启动GDB做一些验尸ananlysis:

It turns out that the segfault occurs not at i=200 but at i=1008, lets figure out why. Start gdb to do some post mortem ananlysis:

$gdb -q ./a.out core

Core was generated by `./a.out'.
Program terminated with signal 11, Segmentation fault.
[New process 4605]
#0  0x080483b4 in main () at seg.c:6
6           q[i]=i;
(gdb) p i
$1 = 1008
(gdb) p &q
$2 = (int (*)[200]) 0x804a040
(gdb) p &q[199]
$3 = (int *) 0x804a35c

问:在结束地址0x804a35c,或者更确切地说,Q的[199]的最后一个字节是在那个位置。页大小是如我们前面4096字节锯和本机的32位字长给出一个虚拟地址分解成一个20位页号和一个12位的偏移

q ended at at address 0x804a35c, or rather, the last byte of q[199] was at that location. The page size is as we saw earlier 4096 bytes and the 32-bit word size of the machine gives that an virtual address breaks down into a 20-bit page number and a 12-bit offset.

Q []虚拟页号结束:

q[] ended in virtual page number:

0x804a = 32842
偏移:

0x804a = 32842 offset:

0x35c = 860
所以仍然有:

0x35c = 860 so there were still:

4096 - 864 = 3232
左字节的内存页上Q []被分配上。空间可以容纳:

4096 - 864 = 3232 bytes left on that page of memory on which q[] was allocated. That space can hold:

四分之三千二百三十二= 808
整数,而code处理它,就好像它包含在位置200的Q元素1008。

3232 / 4 = 808 integers, and the code treated it as if it contained elements of q at position 200 to 1008.

我们都知道,这些因素不存在,且编译器并没有抱怨,也没有硬件,因为我们有写权限到该页面。只有当我= 1008没有Q []是指一个地址不同的页面,我们没有写权限的,虚拟内存硬件检测到这一点,并引发了段错误。

We all know that those elements don’t exists and the compiler didn’t complain, neither did the hw since we have write permissions to that page. Only when i=1008 did q[] refer to an address on a different page for which we didn’t have write permission, the virtual memory hw detected this and triggered a segfault.

这是整数存储在4个字节,这意味着该页面包含808(四分之三千二百三十六)额外假的元素,这意味着它仍然是完全合法的得自q访问这些元素[200],Q [201]一路攀升为元素199 + 808 = 1007(q [1007]),而不会触发赛格故障。当访问Q [1008]你进入一个新的一页其权限是不同的。

An integer is stored in 4 bytes, meaning that this page contains 808 (3236/4) additional fake elements meaning that it is still perfectly legal to access these elements from q[200], q[201] all the way up to element 199+808=1007 (q[1007]) without triggering a seg fault. When accessing q[1008] you enter a new page for which the permission are different.

这篇关于为什么我的程序崩溃时,我写过去的数组的结束?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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