堆中存的都是地址,而且地址对应一个栈中的变量值。
栈中存的都是变量值,在堆中对应一个地址。这么理解堆和栈有问题吗
2条回答 默认 最新
- threenewbee 2019-10-17 13:14关注
首先,你要搞清楚来龙去脉。为什么要有堆和堆栈
我们看一个简单的程序
int n;
int foo(int x)
{
int y = x - 1;
if (y == 0) return 123;
else return foo(y);
}
int main()
{
...
}
注意看int n
int x int y有什么区别?
发现没有,程序里只有一个n,但是,只要foo被调用一次,就必须有一个独立的x和y,如果foo又调用了自身,那么又得来一套x y
并且每次调用的x y都不能干扰到被它调用的那个函数里的x y如果你能理解这个需求,那么就能理解为什么要堆栈。
堆栈的作用就是,当我们调用一次函数的时候,就把这个函数里面的参数、局部变量全部一套放在堆栈上
当我们从函数里返回的时候,函数里变量、参数没用了,我们就收回去。我们向一个方向堆放这些变量,又反方向收回去,所以才用堆栈。如果没有堆栈,管理这些变量非常麻烦。
然后说下堆,堆解决的问题就是程序运行的时候在全局内存里动态分配的存放的问题。比如说
int main() {
scanf("%d", &n);
int * arr = (int *)malloc(sizeof(int) * n);
...
}
这里,arr这个变量是在堆栈上,因为它是一个局部变量。
而它指向的内存,就是在堆上。
堆上这里存放的就是一个数组,而不是你说的,堆上存放指针。
int main() {
int data[100];
scanf("%d", &n);
int * arr = &data[0];
...
}
这个程序,arr指向的是局部变量数组data的首地址,虽然是指针,但是没有用到堆。
只有用new(c++)、 malloc等,才在堆上分配空间。堆的好处在于,它是全局的,所以可以跨函数调用,比如
int * getdata() {
int data[100];
int * arr = &data[0];
return arr;
}
这个程序就不行,因为data是在堆栈上定义的,出了函数就没用了。
得这么写
int * getdata() {
int * arr = (int *)malloc(sizeof(int) * n);
return arr;
}
放在堆上的那块内存,在离开函数后仍然有效。
但是要注意,c语言不会像堆栈那样主动释放堆上的内存,你得注意在不用的时候主动去释放它们,以免占用不必要的空间。堆中存的都是地址(这句话前面已经找到反例了,int * arr = (int *)malloc(sizeof(int) * n); 堆栈中存放的是实际的值),而且地址对应一个栈中的变量值。(不一定,你可以用全局变量、堆上的变量或者任何地方的变量来存储指针,甚至,没有任何变量来存储指针,这个时候,你的程序没办法使用这个地址,也没办法释放它,就叫做内存泄漏)
栈中存的都是变量值,在堆中对应一个地址。
void memleak() {
malloc(sizeof(int) * n);
}
这里,没有任何变量指向分配的空间栈中存的都是变量值,在堆中对应一个地址。栈中也可以是指针
int * arr = (int *)malloc(sizeof(int) * n);
arr就是指针。
栈中还存放了参数和程序的返回地址,不过一般这些对程序员透明。或者说一般程序员是不感兴趣的。但是,注意,黑客是可以利用它做文章的。比如说,黑客可以构造一个超过缓冲区长度的参数,传给一个有缺陷的函数,造成缓冲区溢出,溢出之后,可以改变函数的返回地址,从而执行黑客需要执行的代码
解决 无用评论 打赏 举报
悬赏问题
- ¥15 微信公众号自制会员卡没有收款渠道啊
- ¥15 stable diffusion
- ¥100 Jenkins自动化部署—悬赏100元
- ¥15 关于#python#的问题:求帮写python代码
- ¥20 MATLAB画图图形出现上下震荡的线条
- ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘
- ¥15 perl MISA分析p3_in脚本出错
- ¥15 k8s部署jupyterlab,jupyterlab保存不了文件
- ¥15 ubuntu虚拟机打包apk错误
- ¥199 rust编程架构设计的方案 有偿