繁体   English   中英

弹出堆栈时内存会怎样?

[英]What happens to memory when stack is popped?

我有一个功能

public void f() {
    int x = 72;
    return;
}

因此x可能存储在地址0x9FFF

函数返回后,该地址处的存储器将如何处理? 还在吗? 即该值仍然是72 还是完全无效?

弹出框架后,Java编程语言和Java虚拟机均未定义堆栈框架的内存发生了什么。 这是一个较低层的实现细节,被较高层的抽象所掩盖。 实际上,Java语言和JVM字节码使设计无法从堆栈中检索已删除的值(与C / C ++不同)。

但是实际上,Java中的堆栈框架的行为类似于C中的堆栈框架。不断增长的堆栈将碰撞其指针(通常朝下)并分配空间来存储变量。 缩小堆栈通常会向上移动指针,并简单地将旧值保留在内存中以使其腐烂而不覆盖它们。 如果您具有对JVM的堆栈内存区域的低级访问权限,这是您应该期望看到的行为。

请注意,在Java中不可能像C这样的技巧尝试读取未初始化的堆栈变量:

static boolean firstTime = true;

public void f() {
    int x;
    if (firstTime) {
        x = 72;
        firstTime = false;
    } else {
        // Compile error: Variable 'x' may not have been initialized
        System.out.println(x);
    }
}

在JVM实现中,其他堆栈行为也是可能的。 例如,当弹出框架时,可以将4 KiB虚拟内存页面取消映射回操作系统,这实际上将擦除旧值。 同样在机器架构(例如Mill)上 ,对堆栈存储器也进行了特殊处理,从而使堆栈不断增长将始终返回一个填充有零字节的区域,从而节省了从内存实际加载旧值的工作。

在C语言中,这是未定义的行为

在实践中,如果您尝试以下操作:

 int *ptr;

 void foo() {
    bar();
    printf("%d", *ptr);
 }

 void bar() {
     int x = 72;
     ptr = &x;
 }

然后,很可能是在C大多数实现, foo()将打印72 这是因为尽管ptr引用的地址可用于重新分配,但它尚未被重新分配,也没有任何东西可以覆盖该内存。 程序继续运行的时间越长,初始化更多的局部变量并调用malloc() ,则该内存地址被重用的可能性就越大,并且该值将发生变化。

但是,C规范中没有任何内容说明必须是这种情况-实现可以在范围超出范围时立即将该地址清零,或者在尝试读取它时使运行时出现恐慌,或者好吧,这就是“未定义”是什么意思。

作为程序员,您应注意避免这样做。 很多时候,它会引起的错误会很刺眼,但是在某些时候,您会导致间歇性的错误,这是最难追踪的错误。

在Java中,虽然超出范围的内存可能仍包含72 ,但实际上无法访问它,因此不会影响程序员。 在Java中访问它的唯一方法是对它进行“正式”引用,在这种情况下,它不会被标记为垃圾回收,并且也不会超出范围。

Java中的原始类型放在堆栈中(放入frame局部变量数组中)。 每次调用方法时都会创建一个新框架:

public void foo() {
    int x = 72; // 'x' will be stored in the array of local variables of the frame
}

当框架的方法调用完成时,该框架将被销毁。 此时,所有局部变量部分结果可能仍驻留在堆栈中,但是它们已被放弃并且不再可用。

我不是在看副书,但我猜这在技术上没有定义。

实际上,我曾经在C ++中尝试过一次类似的事情,但如果我没记错的话,实际上是72 (或在函数调用返回之前放置的任何东西),因此机器实际上并没有经过写0到该位置或的东西。

其中一些也是实现细节。 我也用MIPS汇编语言实现了它(如果可以理解的话,我将包括一个代码示例)。 基本上,当我需要寄存器时,我只是通过所需的许多局部变量来“增加”堆栈,将所需的当前值存储在所需的寄存器中(以便以后可以恢复它们),然后重新使用寄存器。 如果是这样的实现,则该值实际上可以包含调用方中的局部变量的值。 不过,我认为这并不是Java所做的。

TL; DR这是一个实现细节,但是至少在C语言中,直到真正需要它时,它才会覆盖内存中的值。 Java很难预测。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM