任何人都可以用C,C ++和Java清楚地解释一下。什么都在堆栈上,什么都在堆上以及何时分配。
我所知道的,
每个函数调用的所有局部变量(无论是基元,指针还是引用变量)都在新的堆栈框架上。
使用new或malloc创建的所有内容都会进入堆。
我对几件事感到困惑。
是在堆上创建的对象成员的引用/基元是否也存储在堆上?
以及在每个框架中递归创建的方法的那些本地成员呢?它们都在堆栈上吗?如果是,那么在运行时是否分配了堆栈内存?同样对于文字,它们是否属于代码段?以及C中的全局变量,C
++ / Java中的static和C中的static。
内存中程序的结构
以下是任何程序在装入内存后的基本结构。
+--------------------------+
| |
| command line |
| arguments |
| (argc and argv[]) |
| |
+--------------------------+
| Stack |
| (grows-downwards) |
| |
| |
| |
| F R E E |
| S P A C E |
| |
| |
| |
| |
| (grows upwards) Heap |
+--------------------------+
| |
| Initialized data |
| segment |
| |
+--------------------------+
| |
| Initialized to |
| Zero (BSS) |
| |
+--------------------------+
| |
| Program Code |
| |
+--------------------------+
需要注意的几点:
数据段
数据段包含由包含初始化值的用户显式初始化的全局和静态数据。
数据段的另一部分称为BSS(因为旧的IBM系统将该段初始化为零)。这是操作系统将内存块初始化为零的内存部分。这就是未初始化的全局数据和静态如何将默认值设为零。该区域是固定的,并且具有静态大小。
基于显式初始化,数据区域被分为两个区域,因为要初始化的变量可以被一对一地初始化。但是,未初始化的变量不需要用0的一对一显式初始化。取而代之的是,初始化变量的工作留给操作系统。批量初始化可以大大减少加载可执行文件所需的时间。
大多数情况下,数据段的布局在底层操作系统的控制之下,但仍有一些加载程序将部分控制权交给用户。该信息在诸如嵌入式系统的应用中可能是有用的。
可以使用代码中的指针来寻址和访问该区域。自动变量在每次需要它们时都具有初始化变量的开销,并且需要代码来进行该初始化。但是,数据区域中的变量没有这样的运行时过载,因为初始化仅执行一次,并且在加载时也进行一次。
代码段
程序代码是可执行代码可用于执行的代码区域。该区域的大小也固定。只能通过函数指针访问,不能通过其他数据指针访问。此处要注意的另一个重要信息是,系统可能将此区域视为只读存储区域,并且任何在该区域中进行写入的尝试都将导致未定义的行为。
常量字符串可以放置在代码或数据区域中,具体取决于实现方式。
尝试写入代码区域会导致未定义的行为。例如(下面我仅给出C
一些示例),以下代码可能会导致运行时错误,甚至使系统崩溃。
int main()
{
static int i;
strcpy((char *)main,"something");
printf("%s",main);
if(i++==0)
main();
}
堆放区
为了执行,程序使用了两个主要部分,即堆栈和堆。堆栈帧是在堆栈中创建的,用于功能;在堆栈中创建的是用于动态内存分配。堆栈和堆是未初始化的区域。因此,存储器中发生的任何事情都将成为在该空间中创建的对象的初始(垃圾)值。
让我们看一个示例程序,以显示哪些变量存储在哪里,
int initToZero1;
static float initToZero2;
FILE * initToZero3;
// all are stored in initialized to zero segment(BSS)
double intitialized1 = 20.0;
// stored in initialized data segment
int main()
{
size_t (*fp)(const char *) = strlen;
// fp is an auto variable that is allocated in stack
// but it points to code area where code of strlen() is stored
char *dynamic = (char *)malloc(100);
// dynamic memory allocation, done in heap
int stringLength;
// this is an auto variable that is allocated in stack
static int initToZero4;
// stored in BSS
static int initialized2 = 10;
// stored in initialized data segment
strcpy(dynamic,”something”);
// function call, uses stack
stringLength = fp(dynamic);
// again a function call
}
还是考虑一个更复杂的例子,
// command line arguments may be stored in a separate area
int main(int numOfArgs, char *arguments[])
{
static int i;
// stored in BSS
int (*fp)(int,char **) = main;
// points to code segment
static char *str[] = {"thisFileName","arg1", "arg2",0};
// stored in initialized data segment
while(*arguments)
printf("\n %s",*arguments++);
if(!i++)
fp(3,str);
}
希望这可以帮助!
问题内容: 假设我有两个陈述。 哪个是堆栈内存,哪个存储在堆中? 两者之间有什么区别? 创建了多少个对象,内存中的引用如何? 最佳做法是什么? 问题答案: 所有对象都存储在堆中(包括其字段的值)。1个 局部变量(包括参数)始终包含原始值或引用,并存储在堆栈中。1个 因此,对于您的两行: 您将在堆上有两个对象(两个包含的String对象)和两个引用(每个对象一个)在堆栈上(提供且是局部变量)。 (实
主要内容:src/runoob/heap/MaxHeap.java 文件代码:一、概念及其介绍 堆(Heap)是计算机科学中一类特殊的数据结构的统称。 堆通常是一个可以被看做一棵完全二叉树的数组对象。 堆满足下列性质: 堆中某个节点的值总是不大于或不小于其父节点的值。 堆总是一棵完全二叉树。 二、适用说明 堆是利用完全二叉树的结构来维护一组数据,然后进行相关操作,一般的操作进行一次的时间复杂度在 O(1)~O(logn) 之间,堆通常用于动态分配和释放程序所使用的对象。 若
我使用GraphDB来存储我的三元组,需要将SpinSail组件堆叠在GraphDB上,以支持自旋规则以及GraphDB默认支持的所有其他功能。 到目前为止,我已经成功地在远程服务器上创建了一个支持Spin规则的存储库(详细信息如下),但它似乎只支持Spin,而不支持GraphDB支持的其他功能(例如查看图表、通过文件添加三元组、搜索等) 创建存储库后,配置文件如下所示: 虽然一个普通的配置文件(
问题内容: 我设法在目录下找到了容器,但是找不到图像。 什么是目录和文件? 问题答案: 目录的内容根据Docker用于存储的驱动程序而有所不同。 默认情况下,这将是,但可以回落到,,,或者根据您的内核支持。在大多数地方,这是可以的,但是RedHats却接受了。 您可以使用Docker守护程序的或选项手动设置存储驱动程序。 将包含驱动程序特定的图像内容存储。 现在在和文件中仅包含有关图像的元数据。
问题内容: 我有一个这样的数组声明: 这是原始类型的数组。该数组存储在哪里?它存储在堆还是堆栈上?这是一个原始类型,所有原始类型都不存储在堆上。 问题答案: 正如gurukulki所说,它存储在堆中。但是,你的帖子提出了一个误解,可能是由于一些善意的人传播了“原始生物始终存在”的神话。这是不正确的。局部变量在堆栈上有其值,但并非所有原始变量都是局部的… 例如,考虑一下: 现在,住在哪里?神话暗示它
我并不了解Java特别是Java调试,但在Jenkins中使用Monitoring进行堆转储,然后在Eclipse中使用MAT对其进行解码,显示总内存使用量为169.4MB,而在Jenkins中Monitoring似乎经常使用内存,GCs也经常运行。-XMX是4G。 为什么我只有169.4MB的mat?可能是因为在进行转储之前,Jenkins执行了GC吗?如果是,我是否可以避免它以看到完整的内存转