美文网首页
C++ 内存模型(1)--static

C++ 内存模型(1)--static

作者: jango_L | 来源:发表于2017-10-12 16:58 被阅读0次

面试过C++的同学都知道,面试官最喜欢问的问题之一就是C++内存模型问题。
例如static 、堆、栈等
网上对这方面的文章很多,但很多都是互相转发。并没有真正验证过。
下面我们通过真实代码来分析C++中,带static的变量的内存布局。

背景:我们知道,在c++中, static 可以用在几个地方:
1)函数修饰变量
2)修饰全局变量
3)类中,修饰类的静态成员变量
4)在类中,修饰表态函数
5)函数定义开头,修饰函数


问题1:函数中static 变量的内存是如何的?

#include "Apple.hpp"

static int g_a = 32;
static int g_b = 32;
static int g_c;

void test(){
    int a = 3;
    int b = 4;
    int c = 3;
    int d = 4;
    
    
    printf("局部变量 a,b,c,d  \n%p  %p  %p  %p\n",&a,&b,&c, &d);
    static int sa = 32;
    static int sb = 32;
    static int sc = 32;
    static int sd;
    
    printf("函数中的 static 变量 \n:sa,sb,sc,sd \n%p  %p  %p  %p\n",&sa,&sb,&sc, &sd);
    
    printf("全局 static 变量 g_a g_b g_c:\n%p %p %p\n",&g_a,&g_b,&g_c);

}

void test1(){
}

int main(int argc, const char * argv[]) {
    // insert code here...
    
    test();
};

输出结果:

0x7fff5fbff7bc  0x7fff5fbff7b8  0x7fff5fbff7b4  0x7fff5fbff7b0
函数中的 static 变量 
:sa,sb,sc,sd 
0x1000020ac  0x1000020b0  0x1000020b4  0x1000020c0
全局 static 变量 g_a g_b g_c:
0x1000020b8 0x1000020bc 0x1000020c4

分析:

//1. g_a, g_b的空间地址是连续的,相差为4,正好和int所占内存空间一致
//2. 地址是递增的。
static int g_a = 32; //0x1000020b8
static int g_b = 32;//0x1000020bc
static int g_c;//0x1000020c4

void test(){
//从a,b,c,d 的空间地址看出,函数的局部变量是存放在栈上,并且空间地址是递减的,这也符合栈空间的特点(众所周知,栈空间逆向生长)。
    int a = 3;//0x7fff5fbff7bc
    int b = 4;//0x7fff5fbff7b8
    int c = 3;//0x7fff5fbff7b4
    int d = 4;//0x7fff5fbff7b0
    
//1. g_a, g_b,g_c的空间地址是连续递增,相差为4,正好和int所占内存空间一致
//2. sd地址断开了
    static int sa = 32;//0x1000020ac
    static int sb = 32;//0x1000020b0
    static int sc = 32;//0x1000020b4
    static int sd;      //0x1000020c0
    

把上面结果的static 变量按地址递增排序为:
sa< sb< sc < g_a < g_b < sd < g_c
可以得出两个结论:
1)函数中的static变量是放到和全局变量个内存区的,也就是全局内容区。
2)编译器给这些static 或 全局变量在内存中的位置为:先函数,再全局。先有值的变量,再无初始值的变量。


问题2:类中的static变量内存是如何分配的

为了搞清楚这个问题,我们先定义一个类Apple
头文件

class Apple{
public:
    static int m_static_num;
};

实现

int Apple::m_static_num = 3;

测试

static int g_a = 32;
static int g_b = 32;
static int g_c ;
int g_d = 3;//新增加

void test(){
    int a = 3;
    int b = 4;
    int c = 3;
    int d = 4;
    
    
    printf("局部变量 a,b,c,d  \n%p  %p  %p  %p\n",&a,&b,&c, &d);
    static int sa = 32;
    static int sb = 32;
    static int sc = 32;
    static int sd;
    
    printf("函数中的 static 变量 \n:sa,sb,sc,sd \n%p  %p  %p  %p\n",&sa,&sb,&sc, &sd);
    
    printf("全局 static 变量 g_a g_b g_c g_d:\n%p %p %p %p\n",&g_a,&g_b,&g_c,&g_d);

}

void test1(){
}

int main(int argc, const char * argv[]) {
    // insert code here...
    
    test();
    
    Apple apple = Apple();
    printf("\napple object address %p , apple member address %p\n",&apple,&apple.m_static_a);
}

输出结果:
注意:以下结果,原全局变量,static变量的地址变化了。是因为原来代码中有些其他未列出的变量。单独分析这次结果不影响。

局部变量 a,b,c,d  
0x7fff5fbff7ac  0x7fff5fbff7a8  0x7fff5fbff7a4  0x7fff5fbff7a0
函数中的 static 变量 
:sa,sb,sc,sd 
0x10000101c  0x100001020  0x100001024  0x100001030
全局 static 变量 g_a g_b g_c:
0x100001028 0x10000102c 0x100001034

apple object address 0x7fff5fbff7c8 , apple member address 0x100001018

分析:
m_static_num <g_d< sa< sb< sc < g_a < g_b < sd < g_c

结论:
1)类的static变量,函数中的static变量,无static的全局变量,带static的全局变量 都是放到同一个内存区,全局内存区。
2)全局变量的初始化顺序,按Bjane的说法是变量定义的先后顺序,不同文件的看编译器具体实现,不做要求。全局变量(包括static)在main函数之前初始化( 动态连接库的情况下是在连接的时候初始化),在main函数结束后清理。

下一章节分析类,函数,指针在内存中的分布

相关文章

  • C++ 内存模型(1)--static

    面试过C++的同学都知道,面试官最喜欢问的问题之一就是C++内存模型问题。例如static 、堆、栈等网上对这方面...

  • C++面向对象编程(下)第二周笔记 GeekBand

    1.对象模型 C++对象模型中,non static数据成员被放置到对象内部,static数据成员,static ...

  • C++_day06

    C++核心编程 主要针对C++面向对象编程技术做详细讲解,探讨C++中的核心和精髓 1. 内存分区模型 C++程序...

  • 原子操作内存序

    [TOC] 参考 1. C++11多线程-内存模型2. c++并发编程1.内存序3. 浅谈Memory Reord...

  • 2018-11-11 #C++ 内存模型#

    C++ 原子操作内存模型 C++ 原子操作内存模型解决并发编程的什么问题? 相信在大多数应用程序员眼里,代码在编辑...

  • 开篇2:C/C++ 内存布局与程序栈

    如果你对C/C++基本数据类型的内存模型没概念的话,可以先查看该传送门《开篇1:C/C++ 内存中的数据表示》,反...

  • C++智能指针和四种转换

    1、智能指针 智能指针,无需手动释放内存 2、C++中的四种转换 const_cast 转换常量 static_c...

  • Java面试核心框架

    常量池 常用关键字 final static 内部类 抽象类 接口 异常 注解 容器 内存管理内存模型、工作内...

  • 智能指针

    内存类型分类 1 静态内存 静态内存用来保存局部static对象,类static数据成员,以及定义在任何函数之外的...

  • 常用面试题目

    java基础:1.JVM内存模型2.juc并发包线程池,容器,线程安全3.static,final作用域、作用4....

网友评论

      本文标题:C++ 内存模型(1)--static

      本文链接:https://www.haomeiwen.com/subject/dmloyxtx.html