美文网首页
NDK_03 C/C++的内存四区模型

NDK_03 C/C++的内存四区模型

作者: HardMan | 来源:发表于2021-08-16 20:18 被阅读0次

导语:内存四区模型是非常重要的一个知识,只有学会从编译器的角度去了解内存是如何分配的,在遇到问题的时候,才能更好的去分析
在掌握四驱模型之前,需要理解几个重要的概念

1.数组参数传递

问题:数组作为参数传递的时候,为什么获取不到长度?
答:数组作为参数传递,会退化成一个指针,传递的是首地址,目的是为了高效。因此在使用数组作为参数时,通常会将长度也作为参数传进去。

2.数据类型

数据类型的本质:内存上一块连续的固定大小空间的别名

3.变量的本质

一段连续内存空间的别名,通过变量可以去操作一块内存上的数据

4.内存四区建立过程

1.操作系统将程序从物理磁盘中load进内存里(运行.exe文件)
2.操作系统把c代码分成四个区
3.操作系统找到main函数入口执行程序

5 四区分析

  • 栈区:由编译器自动分配释放,存放函数的参数、局部变量值等
  • 堆区:一般由程序员分配与释放(malloc、free等函数操作),若程序员不释放,在结束后可能由操作系统进行回收
    -数据区:存放全局变量、静态变量和常量字符串等等,程序结束后由系统进行释放
    -代码区:存放函数体的二进制代码

6 具体分析

1.数据区


#include<stdio.h>

char* getStr1() {
    char* str1 = "hello";
    return str1;
}

char* getStr2() {
    char* str2 = "hello";
    return str2;
}
void main() {

    char* str1 = getStr1();
    char* str2 = getStr2();

    printf("str1的内存地址是:%p  str2的内存地址是:%p \n", str1, str2);

    printf("str1的值是:%s  str2的值是:%s", str1, str2);

}
  结果输出
str1的内存地址是:00627B30  str2的内存地址是:00627B30
str1的值是:hello  str2的值是:hello
image.png

当执行getStr1()方法时,是在数据区当中拿到字符串常量”hello“的地址,并将它赋值给指针str1。可以理解为 str1是数据区 一块内存(内存上的数据为”hello“)的别名。同理 执行getStr2()的时候 同样将该常量的地址赋值给指针str2。

getStr1()和getStr2()方法执行完之后,在main函数中用str1和str2 两个变量来接收返回的指针,即将str1和str2指针都指向到了数据区”hello“字符串的地址 ,因此通过打印可以看出 两个指针的地址相同,数据也相同。

char* str1 = getStr1();
char* str2 = getStr2();
image.png

2.栈区的理解
栈区的内存由编译自动分配与释放

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

char* getStr() {
    char buf[64];
    strcpy(buf, "hello");
    return buf;
}


void main() {

    char* str = getStr();


    printf("str的内存地址是:%p  str的值是:%s \n", str, str);



}

结果:
str的内存地址是:00EFF914  str的值是:烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫\

在这个例子里,发现str的值是乱码,这是由于方法结束时,会将方法内的栈区的内存数据给清空,但地址仍然存在。我们同样画图分析


image.png

在getStr方法中,我们调用strcpy方法,其实是往buf所在的内存中写入数据。但此时,buf指向的仍是栈区内内存。在getStr方法执行完return之后,方法结束,栈区内即buf所指向的内存区域数据清除,但buf仍代表着一个地址,并将这个地址赋值给了main()函数中的str指针,因此该指针有地址,但数据是乱码。

3.堆区

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

char* getStr() {
    
    char* p1 = NULL;
    p1 =(char*) malloc(sizeof(char) * 10);//申请了十个字符大小的内存空间
    if (p1 == NULL) {
        return NULL;
    }


}


void main() {

    char* str = getStr();

    if (str == NULL) {
        printf("str的内存地址是NULL");
    }
    else
    {
        strcpy(str, "0123456789");

        printf("str的内存地址是:%p  str的值是:%s \n", str, str);
    }

}

  结果:
  str的内存地址是:006257C0  str的值是:0123456789
image.png

通过malloc函数在堆区中申请了一段大小为10的内存,p1指针指向了该地址,是该块内存的别名。在getStr()函数结束之后,将指针所指向的地址又赋值给了str,因此str指针也指向了堆区中的这块内存地址


image.png

相关文章

  • NDK_03 C/C++的内存四区模型

    导语:内存四区模型是非常重要的一个知识,只有学会从编译器的角度去了解内存是如何分配的,在遇到问题的时候,才能更好的...

  • c++ 内存四区

    代码区:存放函数体的二进制代码,由操作系统进行管理全局区:存放全局变量和静态变量,以及常量(字符串常量以及其他常量...

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

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

  • C++_day06

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

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

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

  • 内存四区模型

    内存四区分为:栈区、堆区、全局区、代码区 c/c++可以在临时区分配内存,用完后自动被编译器清理 函数1调用函数2...

  • C提高

    1.选择排序 2.内存四区 3. typedef 首先://注意在C和C++里不同在C中定义一个结构体类型要用t...

  • C++11 Memory Model

    Herb Sutter在一次对C++11内存模型的演讲中提到C++11的内存模型,让C++有了标准独立于编译器和平...

  • C++内存模型

    在讲述内存模型的时候,我们使用下面这段代码来涵盖各种内存分配的情况 这是内存变量图: rodata 和 text ...

  • C++内存模型

    普通成员函数存储方式 C++程序的内存格局通常分为四个区:全局数据区(data area),代码区(code ar...

网友评论

      本文标题:NDK_03 C/C++的内存四区模型

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