【无标题】

面试创维时被问到了堆、栈的相关知识,故作此总结。本文为一博客的补充。

博客总结

堆、栈区别:

  1. 申请方式:栈是系统自动分配的,堆需要用malloc、new申请。
  2. 管理方式:系统分配栈时,如果有剩余空间就分配;分配堆时,从空间地址(链表)中找到一个大于所需空间的内存块,分配给程序,如果这个空闲块分配后还有剩余空间,则将剩余部分重新放入链表中。
  3. 效率:栈的分配效率比堆的效率高。
  4. 大小:一般栈比堆小。
  5. 存储内容:看本文即可。
  6. 存取效率:栈比堆快(待验证)。

C++内存布局概述

包括4个部分:

  1. 代码段:只读,存放代码。
  2. 数据段:又分为只读数据段和可读写数据段。只读数据段存储常量、字符串字面值(global)等,可读写数据段存储静态变量(包括全局、局部静态变量)。
  3. 堆:动态分配的内存。
  4. 栈:局部变量。

Code

接下来分析一下具体的代码。
使用gdb查看内存分布。

// C语言源程序
#include <cstdlib>

int ga;
const int gb = 1;
static int gc;
static const int gd = 1;

int main() {
  int la;
  const int lb = 1;
  static int lc;
  static const int ld = 1;
  int *p = (int*)malloc(sizeof(int));
  lc = la; // 使用la,避免编译器优化掉未使用的变量
  return 0;
}
// gdb查看内存分布情况(在编译时使用 gcc -O0 -g a.cc,-O0关闭了编译优化选项)
// 0x555555555000 开头的为代码段
// 0x555555556000 为只读数据段
// 0x555555558000 为可读写数据段
// 0x555555559000 为堆
// 0x7ffffffde000 为栈

(gdb) info proc mappings
process 11481
Mapped address spaces:

          Start Addr           End Addr       Size     Offset  Perms  objfile
      0x555555554000     0x555555555000     0x1000        0x0  r--p   /home/hxd/algo/a.out
      0x555555555000     0x555555556000     0x1000     0x1000  r-xp   /home/hxd/algo/a.out
      0x555555556000     0x555555557000     0x1000     0x2000  r--p   /home/hxd/algo/a.out
      0x555555557000     0x555555558000     0x1000     0x2000  r--p   /home/hxd/algo/a.out
      0x555555558000     0x555555559000     0x1000     0x3000  rw-p   /home/hxd/algo/a.out
      0x555555559000     0x55555557a000    0x21000        0x0  rw-p   [heap]
      0x7ffff7d8b000     0x7ffff7d8e000     0x3000        0x0  rw-p   
      0x7ffff7d8e000     0x7ffff7db6000    0x28000        0x0  r--p   /usr/lib/x86_64-linux-gnu/libc.so.6
      0x7ffff7db6000     0x7ffff7f4b000   0x195000    0x28000  r-xp   /usr/lib/x86_64-linux-gnu/libc.so.6
      0x7ffff7f4b000     0x7ffff7fa3000    0x58000   0x1bd000  r--p   /usr/lib/x86_64-linux-gnu/libc.so.6
      0x7ffff7fa3000     0x7ffff7fa7000     0x4000   0x214000  r--p   /usr/lib/x86_64-linux-gnu/libc.so.6
      0x7ffff7fa7000     0x7ffff7fa9000     0x2000   0x218000  rw-p   /usr/lib/x86_64-linux-gnu/libc.so.6
      0x7ffff7fa9000     0x7ffff7fb6000     0xd000        0x0  rw-p   
      0x7ffff7fbb000     0x7ffff7fbd000     0x2000        0x0  rw-p   
      0x7ffff7fbd000     0x7ffff7fc1000     0x4000        0x0  r--p   [vvar]
      0x7ffff7fc1000     0x7ffff7fc3000     0x2000        0x0  r-xp   [vdso]
      0x7ffff7fc3000     0x7ffff7fc5000     0x2000        0x0  r--p   /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
      0x7ffff7fc5000     0x7ffff7fef000    0x2a000     0x2000  r-xp   /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
      0x7ffff7fef000     0x7ffff7ffa000     0xb000    0x2c000  r--p   /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
      0x7ffff7ffb000     0x7ffff7ffd000     0x2000    0x37000  r--p   /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
      0x7ffff7ffd000     0x7ffff7fff000     0x2000    0x39000  rw-p   /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
      0x7ffffffde000     0x7ffffffff000    0x21000        0x0  rw-p   [stack]
// 查看各种类型的变量分别存储在哪个内存区域
(gdb) print &ga
$1 = (int *) 0x555555558014 <ga>
(gdb) print &gb
$2 = (const int *) 0x555555556004 <gb>
(gdb) print &gc
$3 = (int *) 0x555555558018 <gc>
(gdb) print &gd
$4 = (const int *) 0x555555556008 <gd>
(gdb) print &la
$5 = (int *) 0x7fffffffded4
(gdb) print &lb
$6 = (const int *) 0x7fffffffded0
(gdb) print &lc
$7 = (int *) 0x55555555801c <main::lc>
(gdb) print &ld
$8 = (const int *) 0x55555555600c <main::ld>
(gdb) print p
$9 = (int *) 0x5555555592a0

结论:

  1. 全局变量存放在只读数据段(const)或者可读写数据段(非const);
  2. 局部变量存放在栈(非static)或者数据段(static const在只读数据段,static非const在可读写数据段)。

对于字符串字面值,情况有一点差别:

const char *s1 = "hello"; // s1本身在栈,但它指向的字符串字面值在只读数据段
const char s2[] = "hello"; // s2存放在栈中
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值