为什么这个指针程序不会覆盖所有RAM内存位置?

时间:2017-04-06 18:14:28

标签: c pointers

这是我写的用于覆盖RAM数据并最终导致操作系统崩溃的代码。

#include<stdio.h>
#include<conio.h>
int main(){
    int i=10;
    int *j;
    j=&i;   
    int m=0;
    while(true){
        *(j+m)=m*m; //next location of i
        printf("New Value is. %d \n",(m));       
        m++;
    }
    printf("Complete");
    getch();
    return 0;
}

但是在m为46之后,我的程序才崩溃(m的值可能与编译器不同)。 为什么这个程序以这种方式表现?是因为我们的操作系统提供了一些固定的内存空间来加载&amp;运行程序并超出内存限制会导致程序崩溃吗?

4 个答案:

答案 0 :(得分:2)

问题是,在第一次迭代之后,*(j+m)是无效的内存访问,导致undefined behavior。然后,没有,绝对没有任何保证。

你的情况下,它恰好发生在索引46之前,可以从进程访问内存位置(即,该位置属于进程的virtual address space,但这并不意味着您可以访问,您可能会覆盖其他一些数据)并且超过该索引,您的进程无法访问内存位置,因此会发生访问冲突,从而导致段错误。

答案 1 :(得分:2)

您正在覆盖堆栈,从本地变量中销毁数据并从当前函数的过程指针返回到之前调用的所有其他函数,直到您到达只读内存的一部分,因为它包含实际的代码你的程序,这部分是受保护的。当你试图覆盖它时,系统会阻止它,并且应用程序会因“无法写入内存”错误而崩溃。

不确定Linux,但在Windows中,您可以使用VirtualProtect()对此内存进行解除保护。但这样做只会让你在使用垃圾覆盖循环代码并在分段错误错误中死亡时会稍微崩溃。

但是,您仍然无法访问计算机的实际RAM,甚至无法知道您所在的真实RAM中的实际地址。当您是操作系统下的进程时,您处于虚拟内存领域,操作系统将保证您不会直接干扰系统或其他进程的内存,而无需通过系统为您提供的通道。

答案 2 :(得分:2)

首先理解一件事......根据C语言的规则,访问最初未定义的内存块会导致未定义的行为!

现在未定义的行为严重未定义。在我的情况下,当我运行程序时,它只在m = 1后崩溃。

定义未定义的意义背后没有逻辑。未定义的行为可能不仅取决于导致它的原因,还取决于其他几个问题。

答案 3 :(得分:1)

除了你的程序包含一个未定义的行为,因为你试图访问你没有以某种方式分配的内存,你观察到的是你的程序运行的OS确保的一些保护上。

操作系统通过空间块管理分配给运行程序的空间是很常见的。这样的块通常称为页面页面是操作系统可以代表进程管理的更精细的内存。因此,即使访问变量i的下一个内存地址在逻辑上是错误的(未定义的行为),生成的机器代码显然可能会尝试获取内存内容。此时OS / CPU / MMU仅验证该地址是否在您的进程的页面中。因此,仅当您访问不在流程空间中的页面时才会出现崩溃。

如果您想了解更多详情,请参阅虚拟内存页面错误 ...