一、C
一个由c/C++编译的程序占用的内存分为以下几个部分
1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放
4、文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放
5、程序代码区—存放函数体的二进制代码。
例子程序
这是一个前辈写的,非常详细
//main.cpp
int a = 0; 全局初始化区
char *p1; 全局未初始化区
main()
{
int b; 栈
char s[] = "abc"; 栈
char *p2; 栈
char *p3 = "123456"; 123456\0在常量区,p3在栈上。
static int c =0; 全局(静态)初始化区
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);
分配得来得10和20字节的区域就在堆区。
strcpy(p1, "123456"); 123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。
}
二、Python
Python是用C实现的。
在python世界中,一切都是对象。整数、字符串、类型(如字符串类型)等都是对象。面向对象理论中的“类”“对象”在python中都是通过python内的对象实现的。
在python中,对象就是:为C 中的结构体在堆上申请的一块内存。
所有的内建的类型对象(如整数类型对象、字符串类型对象)都是被静态初始化的。
在python中,一个对象一旦被创建,它在内存中的大小就是不变的(而java在堆new的对象是在运行时动态分配内存的)。如果要容纳可变长度数据的对象,只能在对象内维护一个指向一块可变大小的内存区域。
和java、c#一样,python提供了对内存的垃圾收集(GC)机制。
python中所有的内存管理机制都有两套实现。这两套实现由编译符号PYMALLOC_DEBUG控制。
当该符号被定义时,使用debug模式下的内存管理机制。这套机制在正常的内存管理动作之外,还会记录许多关于内存的信息,以方便python在开发时进行调试。
当该符号未被定义时,python的内存管理机制只进行正常的内存管理动作。
三、Java
Java把内存划分为4个部分 :
1、栈区(stacksegment)—由编译器自动分配释放,存放函数的参数值,局部变量的值等,具体方法执行结束之后,系统自动释放JVM内存资源。
2、堆区(heapsegment)—一般由程序员分配释放,存放由new创建的对象和数组,jvm不定时查看这个对象,如果没有引用指向这个对象就回收。
3、静态区(datasegment)—存放全局变量,静态变量和字符串常量,不释放
4、代码区(codesegment)—存放程序中方法的二进制代码,而且是多个对象共享一个代码空间区域。
Java自动管理栈和堆,程序员不能直接地设置栈或堆。
当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。
在堆中产生了一个数组或对象后,还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。
栈有一个很重要的特殊性,就是存在栈中的数据可以共享。
要注意这种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的,因为这种情况a的修改并不会影响到b, 它是由编译器完成的,它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态,会影响到另一个对象引用变量。