java - 弹出堆栈时内存会发生什么情况?

标签 java c jvm

我有一个函数

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

所以x可能存储在地址0x9FFF

当函数返回时,那个地址的内存会发生什么?它还在那里吗?即值仍然是 72 吗?还是完全失效?

最佳答案

在 C 中它是未定义的行为

在实践中,如果你要尝试这样的事情:

 int *ptr;

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

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

那么可能在大多数 C 实现中,foo() 将打印 72。这是因为虽然 ptr 引用的地址可用于重新分配,但它不太可能已经被重新分配,并且没有任何内容覆盖该内存。你的程序继续运行的时间越长,初始化更多的局部变量,调用malloc(),这个内存地址就越有可能被重新使用,值就会改变。

然而,C 规范中没有任何内容表明必须如此 - 一个实现可以一旦该地址超出范围就将该地址归零,或者在您尝试读取时使运行时 panic 它,或者,嗯,任何东西——这就是“未定义”的意思。

作为一名程序员,您应该注意避免这样做。很多时候它会导致的错误会很明显,但有时您会导致间歇性错误,这是最难追踪的错误。

在 Java 中,虽然在超出范围后内存可能仍然包含 72,但实际上没有办法访问它,因此它不会影响程序员。可以在 Java 中访问它的唯一方法是如果有对它的“官方”引用,在这种情况下,它不会被标记为垃圾收集,也不会真的超出范围。

关于java - 弹出堆栈时内存会发生什么情况?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43441301/

相关文章:

java - Spring集成和多线程,丢失了必需的 header

c - 如何将 .txt 文件中的值读取到 C 程序中

c - 遍历字符数组并打印字符

clojure - Frege 是否执行尾调用优化?

java - jvm的抽象机器概念

java - 通过数据库或算法比较不同日期的两个对象

java - jMeter - 调用 jmx 操作

c - 将指针作为局部变量的函数的汇编指令

java - 是否可以在Java进程启动后启用调试而无需调试

java - 更改Java程序中反斜杠指向的根目录