可能重复:
堆栈和堆的内容和位置
我在堆栈和堆上有几个问题.
要知道的基本事情是堆栈比堆快,但是有限.(如我错了请纠正我).
但是,我总是想知道堆栈和堆是如何工作的.RAM只是一块内存,它不分为'堆栈'和'堆'(或者是它?).如果是这样,为什么我们首先将堆栈和堆中的内存分开?
操作系统可以让我们能够分配堆栈中的所有内容 - >一切都变得更快 - >幸福的世界?
我很确定事实并非如此.但为什么!?谁能给我一个深入的答案?
很抱歉,如果这篇帖子是某人发过的一些帖子的副本,那么有很多与堆栈和堆相关的帖子,我找不到我所拥有的确切问题.如果您碰巧知道一个,请继续并将其链接.
我正在使用MinGW和GCC 3.4.5(mingw-special vista r3).
我的C应用程序使用了大量的堆栈,所以我想知道是否有任何方法可以以编程方式告诉剩余多少堆栈,因此如果我发现我即将耗尽,我可以干净地处理这种情况.
如果没有其他方法可以解决可能耗尽堆栈空间的问题?
我不知道我将从哪个堆栈大小开始,因此需要以编程方式识别.
我的代码经常将C++字符串转换为CStrings,我想知道原始字符串是否在堆栈上分配,CString也会在堆栈上分配吗?例如:
string s = "Hello world";
char* s2 = s.c_str();
Run Code Online (Sandbox Code Playgroud)
会s2在堆栈上还是在堆中分配?换句话说,我需要删除s2吗?
相反,如果我有这个代码:
string s = new string("Hello, mr. heap...");
char* s2 = s.c_str();
Run Code Online (Sandbox Code Playgroud)
请问s2现在在堆中,因为它的起源是在堆上?
为了澄清,当我询问是否s2在堆上时,我知道指针在堆栈上.我问的是它指向堆或堆栈的内容.
我想在swift中不希望存储在堆栈/堆中的内容.我有一个很好的估计:你打印的所有东西和内存地址都不是值,它们存储在堆栈中,而是打印出的值是什么,它们在堆上,基本上根据值和引用类型.我完全错了吗?并且可选地,您是否可以提供堆栈/堆的可视化表示?
不幸的是,只能通过"pop"从堆栈中删除项目.堆栈没有"删除"方法或类似的东西,但我有一个堆栈(是的,我需要一个堆栈!),我需要从中删除一些元素.
有这个诀窍吗?
今天我试图在java.util.Stack课堂上推进,然后Iterator通过项目使用迭代(不使用pop).我期待着LIFO的财产但却感到惊讶.
这是我正在尝试的代码.
import java.util.*;
import java.util.Stack;
public class Main {
public static void main(String[] args) {
RobStack<Integer> rstack = new RobStack<Integer>(); // Correct Implementation
Stack<Integer> jstack = new Stack<Integer>(); // Default Java Implementation
rstack.push(0); jstack.push(0);
rstack.push(1); jstack.push(1);
rstack.push(2); jstack.push(2);
rstack.push(3); jstack.push(3);
System.out.print("Algo Stack: ");
for (int i : rstack)
System.out.print(i + " ");
System.out.print("\nJava Stack: ");
for (int i : jstack)
System.out.print(i + " ");
}
}
Run Code Online (Sandbox Code Playgroud)
以上程序的输出如下:
Algo Stack: 3 2 1 0
Java Stack: …Run Code Online (Sandbox Code Playgroud) 我可以理解旧PPC RISC系统的这个要求,甚至是x86-64,但是对于旧的,经过验证的x86?在这种情况下,堆栈只需要在4字节边界上对齐.是的,某些MMX/SSE指令需要16字节对齐,但如果这是被调用者的要求,则应确保对齐正确.为什么要为每个来电者增加这项额外要求?这实际上可能会导致性能下降,因为每个呼叫站点都必须管理此要求.我错过了什么吗?
更新:在对此进行一些调查并与一些内部同事进行一些咨询后,我对此有一些理论:
我对最后一项的问题是,对于依赖于被调用者清理堆栈的调用约定,上述要求实际上 "uglify"了codegen.例如,某些编译器决定为自己的内部使用实现更快的基于寄存器的调用样式(即任何不打算从其他语言或源调用的代码)?这种堆栈对齐可能会通过在寄存器中传递一些参数来抵消一些性能提升.
更新:到目前为止,唯一真正的答案是一致性,但对我来说,答案有点太容易了.我有超过20年的x86架构经验,如果一致性,而不是性能,或其他具体的东西,那么我真的是因为我恭敬地建议开发人员要求它有点天真.他们忽略了近三十年的工具和支持.特别是如果他们期望工具供应商能够快速轻松地为他们的平台调整他们的工具(可能不是......这是 Apple ......),而不必跳过几个看似不必要的箍.
我会在另一天左右给出这个话题,然后关闭它......
我在课本中读到堆栈通过减少内存地址而增长; 也就是说,从较高地址到较低地址.这可能是一个糟糕的问题,但我没有把这个概念弄好.你可以解释吗?
是否有一个有效的方法来删除一个范围-比如尾部-从X的元素List,例如LinkedList在Java中?
显然可以逐个删除最后的元素,这应该导致O(X)级别的性能.至少在LinkedList某些情况下,应该可以具有O(1)性能(通过设置要移除的第一个元素周围的引用并设置头/尾引用).不幸的是,我没有看到任何方法List或LinkedList一次性删除最后的元素.
目前我正在考虑使用替换列表,List.subList()但我不确定它是否具有相同的性能.至少在代码中会更清楚,另一方面,我会放弃LinkedList提供的附加功能.
我主要使用List作为堆栈,这LinkedList似乎是最好的选择,至少在语义方面.
用于演示目的的简单类:
public class Main {
private static int counter = 0;
public static void main(String[] args) {
try {
f();
} catch (StackOverflowError e) {
System.out.println(counter);
}
}
private static void f() {
counter++;
f();
}
}
Run Code Online (Sandbox Code Playgroud)
我执行了5次上面的程序,结果是:
22025
22117
15234
21993
21430
Run Code Online (Sandbox Code Playgroud)
为什么结果每次都不同?
我尝试设置最大堆栈大小(例如-Xss256k).然后结果更加一致,但每次都不相等.
Java版本:
java version "1.8.0_72"
Java(TM) SE Runtime Environment (build 1.8.0_72-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.72-b15, mixed mode)
Run Code Online (Sandbox Code Playgroud)
编辑
当JIT被禁用时(-Djava.compiler=NONE)我总是得到相同的数字(11907).
这是有道理的,因为JIT优化可能会影响堆栈帧的大小,并且JIT完成的工作肯定必须在执行之间变化.
尽管如此,我认为如果通过参考关于该主题的一些文档和/或JIT在这个特定示例中完成的工作的具体示例来确认该理论将导致框架大小改变将是有益的.