C++基础之内存分配


前言

个人笔记


一、程序内存布局

       应用程序运行在一个虚拟内存空间里,32位的系统,寻址空间为232 = 4G,最大只能支持4G内存;而64位的系统,寻址空间为264 ,理论上可以支持很大的内存。大部分操作系统都将内存空间的一部分分给内核调用,应用程序不能直接访问这段内存,这一部分内核地址成为内核态空间。这里以32位系统为例,Linux默认将高地址的1G空间分配给内核作为内核态空间,剩下的3G空间作为用户态空间,而用户态一般有以下4个默认区域:

  • 1、栈区:由编译器自动分配释放,存放函数的参数值、局部变量的值等。操作方式类似于数据结构中的栈。
  • 2、堆区:一般由程序员分配释放,它与数据结构中的堆是两个概念,分配方式类似于链表。
  • 3、读写段:全局变量与静态变量的存放在同一块区域(读写段),在程序编译时分配。
  • 4、只读段:
    • 4.1、文字常量区:一般存放常量字符串,在只读段的高地址。
    • 4.2、程序代码区:存放函数体的二进制代码,比如类的成员函数、全局函数,在只读段的低地址。

代码如下(示例):

#include <iostream>

int a;//全局区,默认会赋初值等于0
char *p;//全局区,默认是null

int main()
{
    int b;//栈区,默认随机值
    char *p1;//栈区,该指针会乱指一通(野指针)
    static int c = 30;//全局静态区
    const char *pstr = "hello,world";//pstr本身位于栈区,指向的值位于文字常量区
    int *p3 = new int(40);//p3本身位于栈区,指向的变量位于堆区

    printf("\n打印变量的地址\n");
    printf("&a = %p\n", &a);
    printf("&p = %p\n", &p);
    printf("p = %p\n", p);

    printf("&b = %p\n", &b);
    printf("&p1 = %p\n", &p1);
    printf("p1 = %p\n", p1);

    printf("&c = %p\n", &c);

    printf("&pstr = %p\n", &pstr);
    printf("pstr = %p\n", pstr);
    printf("hello,world = %p\n", &"hello,world");

    printf("&p3 = %p\n", &p3);
    printf("p3 = %p\n", p3);
    printf("&main = %p\n", &main);//程序代码区
    printf("main = %p\n", main);//程序代码区

    printf("\n打印变量的值\n");
    printf("a = %d\n", a);
    printf("b = %d\n", b);

    delete p3;
    p3 = nullptr;
    return 0;
}

       执行一个非内置的程序时,加载器会将可执行目标文件中的代码和数据从磁盘拷贝到内存中。每个Linux程序都会有一个运行时存储器映像,虚拟内存空间如图所示。

  • 1、在32位系统下,代码段总是从地址0x08048000处开始。
  • 2、数据段是在接下来的下一个4KB对齐的地址处。
  • 3、运行时堆(heap)在读写段之后接下来的第一个4KB对齐的地址。
    虚拟内存空间

二、栈与堆的比较

       栈与堆有以下几个方面不同:

  • 1、栈由编译器自动管理,无需手动控制,速度快;堆需要程序员控制,速度慢,容易产生内存泄漏(memory leak)。
  • 2、栈的内存大小一般较小,而堆内存几乎没有什么限制。
  • 3、对于栈来说,分配方向是朝着内存地址减小的方向;对于堆来,分配方向是朝着内存地址增加的方向。
  • 4、对于堆来说,频繁的new/delete会导致内存空间不连续,造成大量的碎片,使得程序效率降低;对于栈来说,则不会存在这个问题。
  • 5、堆都是动态分配,由malloc、calloc等函数进行分配;而栈的动态分配是由编译器进行分配释放,无需手动实现;静态分配由编译器完成,比如局部变量的分配,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值