内存四区之堆栈区

17 篇文章 1 订阅

一、堆区

先看一个例子:

#include"stdio.h"
#include"stdlib.h"
#include"string.h"

char* getval(int num) {
    char* p = NULL;
    p = (char*)malloc(sizeof(char) * num);
    strcpy(p, "123456789");
    if(p == NULL)
        return NULL;
    printf("p: %s\n", p);
    printf("p: %d\n", p);
    return p;
}

int main() {
    char* p = NULL;
    p = getval(10);
    if (p == NULL)
        return;
    strcpy(p, "321");
    printf("p: %s\n", p);
    printf("p: %d\n", p);
    system("pause");
    return 0;
}

输出结果:

这里写图片描述

可以看到main函数中的p与被调函数getval中的p所指向的地址是相同的,画个图说明一下:

这里写图片描述

首先main函数中的指针p压栈,

char* p = NULL;

调用getval函数时,getval函数中的指针p压栈,

p = getval(10);
char* p;

p申请了num个字节的空间,这段空间是在堆区申请的,p指向这段申请的堆区空间,

p = (char*)malloc(sizeof(char) * num);

通过strcpy向p所指向的内存块中写入数据(注意,不是向p中写入数据)

strcpy(p, "123456789");

getval调用完毕,返回p所指向的首地址,p指针被释放,但p所指向的首地址在堆区,由操作系统管理,并没有被free掉,仍然存在,main函数中的p指针同样也指向了这个首地址,并通过strcpy修改了这段内存的内容:

strcpy(p, "321");

二、栈区

以同样的例子再来看一下栈区的情况:

#include"stdio.h"
#include"stdlib.h"
#include"string.h"

char* getval() {
    char p[64];
    strcpy(p, "123456789");
    printf("p: %s\n", p);
    printf("p: %d\n", p);
    return p;
}

int main() {
    char* p = NULL;
    p = getval();
    if (p == NULL)
        return;
    strcpy(p, "321");
    printf("p: %s\n", p);
    printf("p: %d\n", p);
    system("pause");
    return 0;
}

输出结果:

这里写图片描述

可以看到main函数中的p输出了乱码,再画个图说明一下:

这里写图片描述

前面的压栈操作跟堆区的那个例子是一样的,就不重复说了,这里getval函数中的p是个char类型的数组,编译器在栈上为p分配了64个字节,p指向栈区中这段内存的首地址(注意getval函数return的是内存首地址,并不是整个内存块),通过strcpy向这段栈区内存中写入数据,

strcpy(p, "123456789");

然后返回p所指向的地址,因为是在栈上开辟的内存空间,出了getval函数之后,会自动被析构回收,这段内存可能空着,也可能被分配给其他变量了,main函数中的p指针仍然指向这段被释放的空间,即使往里面写东西,也只会出现乱码,让这种情况发生很有可能让计算机down掉,所以这是一种很危险的编写代码行为,切忌切忌!

刚才的结果截图是debug下的,再来个release下的:

这里写图片描述

诶!发现这里main函数中p成功修改了指向栈空间的内存,其实吧,debug和release下的处理方式不同,这样的代码在两个不同版本下的结果不同,这是相当不稳定的代码,总之这种情况实际编写代码中是不允许的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值