程序内存分配

____________________

| Stack区(栈区)(函数参数,局部变量,数组);自动创建,函数结束时自动释放,速度快,容量小

|____________________

| Static存储区(static变量,全局变量); 程序编译的时候就分配好

|____________________

|                                                     ; 通过malloc/new等资源申请函数分配,需要程序员主动释放

| Heep区(堆区) 比较大              ; 速度慢,容量大

|____________________

| 代码段

____________________

//main.cpp

int a = 0; // 全局初始化区

char *p1;  // 全局未初始化区

main()

{

static int c =0;         // 全局(静态)初始化区

int b;                           // 栈

char *p2;                    // 栈

char s[] = "abc";         // s在栈, "abc"+‘\0‘在文字常量区

char *p3 = "123456";      // p3在栈,"123456" + ‘\0‘在常量区

p1 = (char *)malloc(10);  // 分配得来得10字节的区域在堆区

p2 = (char *)malloc(20);  // 分配得来得20字节的区域在堆区

strcpy(p1, "123456");     // "123456" + ‘\0‘在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。

}

1. 栈的访问速度快,只需要移动栈顶指针就可以;

2. 函数局部变量在栈里面,栈的空间有限(1MB-2MB),在函数里面声明一个非常大的数组有可能是会出错的;

3. 特别注意递归函数醉倒不要使用大的栈对象,因为随着递归深度的增加,所需要的栈空间也线性增加,有可能出现栈溢出;

4. 栈里面的变量由系统维护,函数退出的时候,这些变量自动释放,这里有变量作用域的概念;

5. 编译器使用栈来存放函数的参数;

6. 栈是线程独立的,每个线程都有自己的栈。

1. 堆的创建和销毁由程序员完成,灵活但容易出错;

2. 堆的创建需要在空闲存储列表上查找匹配块的过程,因此会比较慢。尤其当找不到空闲块适应当前空间申请大小时,会引发存储区整理功能,极具脱慢堆对象的创建。堆对象释放的时候也可能会相邻空闲块的合并等操作;

3. 如果分配了堆对象,却忘记了释放,就会产生内存泄漏。泄露的内存在程序退出时会被操作系统回收,但如果程序长期的执行,并有经常性的内存泄露,这样就会耗尽系统所有的内存资源,包括虚拟内存,这时候系统的任何操作都会变得剧慢无比,甚至直接系统崩溃。因此内存泄露一定要足够重视,并使用专用的工具检测程序;

4. free(ptr);如果不调用ptr=NULL;那么ptr就成为所谓的“悬挂指针”,如果程序某个地方在此使用ptr就会出现非法访问,严重时就导致程序崩溃。因此一个好的习惯是将free(ptr); ptr=NULL;写在一起;

5. 堆是开在内存里面的,但当物理内存不够时,如果还需要生成新的堆对象,通常不会产生运行错误,因为系统会使用虚拟内存来扩展实际的物理内存。

申请堆对象的函数有:malloc和calloc

(1) malloc  在堆区分配指定字节数的存储区,此存储区中的初始值不确定。

(2) calloc  在堆区为指定长度的对象,分配能容纳其指定个数的存储空间。该空间中的每一字节都初始化为0

(3) realloc 更改以前存储区的长度(增加或减少)。当增加长度时,可能需将以前存储区的内容复制到另一个足够大的区域,而新增区域内的初始值则不确定。

buff = calloc(numElements ,sizeOfElement);

等价于

  buff = malloc(numElements *sizeOfElement);

memset(buff, 0, numElements *sizeOfElement);

实现malloc的方法有很多种,但一个申请到的存储区结构大概都会包括:1.状态(使用/空闲); 2.长度;3.存储地址;4.下一端存储区地址

buff = malloc(size);

对于用户可见的就是buff这个存储地址,用户可以使用的存储空间是 [buff ... buff+size]。而系统除了给出buff这个地址外,还需要知道这个buff的长度,因为在free(buff)的时候,用户并没有输入长度信息,需要系统自己记录下buff的size。这就需要额外的一些字节。一般这些信息会记录在buff前面的几个地址空间内。因此对于系统来说,buff这个存储空间,对应的实际空间为 [buff-n ... buff+size+n]。buff地址前的部分数据用户不可见,但是是非常重要的,如果程序中有buffer超界的情况,而恰好该buffer后面紧接着另一个buffer,这个超界就是极端可怕的,因为它写花了下一个buffer的长度信息,会引起完全不可知的程序错误。而且这种错误编译器是发现不了,只有一些动态程序分析工具可以run-time的检测到这些错误。所以使用动态buffer时一定要清楚的知道它的大小,以及当前位置。

时间: 2024-10-01 00:12:38

程序内存分配的相关文章

C/C++程序内存分配(和Linux进程分配有一些区别)

C/C++程序内存分配 一.一个由C/C++编译到程序占用的内存分为以下几个部分: 1.栈区(stack)--由编译器自动分配释放,在不需要的时候自动清除.用于存放函数的参数.局部变量等.操作方式类似数据结构中的栈(后进先出). 2.堆区(heap)--一般由程序员分配释放,若程序员分配后不释放,程序结束后可能由OS回收.不同于数据结构中的堆,分配方式有些类似链表. 3.全局区(静态区)--全局变量和静态变量存储在这里.程序结束后由系统释放.在以前到C语言中,全局变量又细分为初始化的(DATA段

c#程序内存分配

c#程序内存分配 进程可使用内存数就是操作系统给进程分配的最大地址,一般的32位操作系统提供给用户地址最大都是3g(操作系统自己保留1g),windows由于商业目的,对于个人用户只提供了2g地址,要使用3g扩展需要对系统配置作修改.还有就是intel的32位芯片实际上是支持36位寻址能力的(64g),但是也是出于商业目的对于大部分个人芯片都禁止了这个功能,这个禁止可能是物理上的限制个人用户几乎无法修改. 而且在操作系统中物理可用内存和进程实际占用内存是有区别的,因为有虚拟地址和交换区这种概念,

c语言程序内存分配

转自: http://book.51cto.com/art/200811/96138.htm C语言编译后的可执行程序的存储结构和运行结构 可执行程序在存储时(没有调入到内存)分为代码区(text).数据区(data)和未初始化数据区(bss)3个部分. (1)代码区(text segment).存放CPU执行的机器指令(machine instructions).通常,代码区是可共享的(即另外的执行程序可以调用它),因为对于频繁被执行的程序,只需要在内存中有一份代码即可.代码区通常是只读的,使

C程序内存分配

在多任务操作系统中的每一个进程都运行在一个属于它自己的内存沙盘中.这个沙盘就是虚拟地址空间(virtual address space),在32位模式下它总是一个4GB的内存地址块.这些虚拟地址通过页表(page table)映射到物理内存,页表由操作系统维护并被处理器引用.每一个进程拥有一套属于它自己的页表,但是还有一个隐情.只要虚拟地址被使能,那么它就会作用于这台机器上运行的所有软件,包括内核本身.因此一部分虚拟地址必须保留给内核使用: 这并不意味着内核使用了那么多的物理内存,仅表示它可支配

C/C++程序内存分配详解

一.常见的几个区 1.栈区(stack)程序运行时由编译器自动分配,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构中的栈.程序结束时由编译器自动释放. 2.堆区(heap)在内存开辟另一块存储区域.一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 .注意它与数据结构中的堆是两回事,分配方式倒是类似于链表. 3.全局区(静态区)(static) 编译器编译时即分配内存.全局变量和静态变量的存储是放在一块的,初始化的 全局变量和静态变量在一块区域, 未初始化的全局变量和未

C++程序内存分配方式(堆与栈)

一.内存布局 1.栈区(stack):由编译器自动分配释放,存放函数的参数值,局部变量值等,其操作方法类似数据结构中的栈. 2.堆区(heap):一般由程序员分配释放,与数据结构中的堆毫无关系,分配方式类似于链表. 3.全局/静态区(static):全局变量和静态变量的存储是放在一起的,在程序编译时分配. 4.文字常量区:存放常量字符串. 5.程序代码区:存放函数体(类的成员函数.全局函数)的二进制代码 二.栈与堆的比较 1.申请方式 stack:系统自动分配,如声明int a;系统自动在栈空间

C/C++——程序的内存分配

C/C++程序内存分配 一.预备知识-程序的内存分配 一个由c/C++编译的程序占用的内存分为下面几个部分 1.栈区(stack):由编译器自己主动分配释放 ,存放函数的參数值,局部变量的值等.其操作方式相似于数据结构中的栈. 2.堆区(heap): 一般由程序猿分配释放, 若程序猿不释放,程序结束时可能由OS回收 .注意它与数据结构中的堆是两回事.分配方式倒是相似于链表,呵呵. 3.全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,

内存分配方式及内存碎片

什么是内存碎片? 内部碎片的产生:因为所有的内存分配必须起始于可被 4.8 或 16 整除(视 处理器体系结构而定)的地址或者因为MMU的分页机制的限制,决定内存分配算法仅能把预定大小的内存块分配给客户.假设当某个客户请求一个 43 字节的内存块时,因为没有适合大小的内存,所以它可能会获得 44字节.48字节等稍大一点的字节,因此由所需大小四舍五入而产生的多余空间就叫内部碎片.外部碎片的产生: 频繁的分配与回收物理页面会导致大量的.连续且小的页面块夹杂在已分配的页面中间,就会产生外部碎片.假 设

C语言中内存分配

C语言中内存分配 在任何程序设计环境及语言中,内存管理都十分重要.在目前的计算机系统或嵌入式系统中,内存资源仍然是有限的.因此在程序设计中,有效地管理内存资源是程序员首先考虑的问题. 第1节主要介绍内存管理基本概念,重点介绍C程序中内存的分配,以及C语言编译后的可执行程序的存储结构和运行结构,同时还介绍了堆空间和栈空间的用途及区别. 第2节主要介绍C语言中内存分配及释放函数.函数的功能,以及如何调用这些函数申请/释放内存空间及其注意事项. 3.1 内存管理基本概念 3.1.1 C程序内存分配 1