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

2021-08-16  本文已影响0人  HardMan

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

1.数组参数传递

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

2.数据类型

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

3.变量的本质

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

4.内存四区建立过程

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

5 四区分析

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
上一篇 下一篇

猜你喜欢

热点阅读