关于C/c++内存分配问题
发布网友
发布时间:2023-08-31 20:14
我来回答
共3个回答
热心网友
时间:2023-09-17 14:51
前者和后者都一样犯了同一个错误
由于变量是在栈中分配 每个程序都有自己的栈,也就是这里面的数据不会被其他的程序修改,但是可能会被你自己修改。
所以当你立刻返回这个地址,并且立刻按照正确的类型读取它那么你所获得的值是正确的.这就是你的试验结果 看起来没有什么错误.
但是这种小"技巧"很可能让你的程序崩溃或者运行结果谬之千里。因为当你返回了已经释放的局部变量的内存的时候。那块内存可以被分配给其他变量,也就是说你的指针指向的是一块不知道属于哪个变量的内存.因为这块内存随时可以分配给程序中的其他变量.并且值会随之改变.
请看如下代码:
#include <stdio.h>
#include <stdlib.h>
int *fun()
{
int *pi;
int i=3;
pi=&i;
printf("fun: %p\n",pi);
return pi;
}
int *fun2()
{
int *pi;
int i=7;
pi=&i;
printf("fun1: %p\n",pi);
return pi;
}
int main(void)
{
int*p=fun();
p=fun();
printf("%p\n",p);
p=fun2();
printf("%p\n",p);
system("pause");
}
你会发现fun()和fun2()中的局部变量的地址是一样的
也就是说fun()返回的指针所指向的内存,p指向的内存随时会意外改变
再试试如下代码
#include <stdio.h>
#include <stdlib.h>
int *fun()
{
int *pi;
int i=3;
pi=&i;
printf("fun: %p\n",pi);
return pi;
}
int *fun2()
{
int *pi;
int i=7;
pi=&i;
printf("fun1: %p\n",pi);
return pi;
}\
int * funset(int k){
int *pi;
int i=k;
printf("funset: %p\n",&i);
return &i;
}
int main(void)
{
int*p=fun();
printf("%p\n",p);
printf(" %d\n\n",*p);//输出p指向的内存值
p=fun();
printf("%p\n",p);//第二次调用fun(),p没有改变 说明两次调用函数局部变量用的是同一块内存,也就是内存被重新分配了。
printf(" %d\n\n",*p);
p=fun2();
printf("%p\n",p);//调用另一个函数p还是局部变量地址还是没变,这个函数用得还是同一块内存。
printf(" %d\n\n",*p);
p=funset(100);//猜猜这个函数干了什么,你就会明白.
//我猜你没有打算改变p所指向的内存吧。
printf("%p\n",p);//调用另一个函数p还是局部变量地址还是没变,这个函数用得还是同一块内存。
printf(" %d\n\n",*p);
system("pause");
}
----------
书上说不要返回局部变量的地址就是因为这个地址指向的内存已经是free的
随时可以分配给别的变量。
free的内存,它不是由你使用的,而是由程序自动使用,程序会随时让这个内存发生你没打算干的改变.比如分配给别的局部变量,栈的分配工作是在编译期决定的。不是动态分配。
-----------
你再想想假如你做了如下的事情
返回了一个局部变量的地址保存到p中
你以为这块内存没有变化并且打算利用这块内存保存点东西。
然后调用了一个函数。
然后你莫名其妙的发现p所指向的内存莫名其妙的变化了。
热心网友
时间:2023-09-17 14:52
main中返回的地址当然和函数内的数组地址是相同的,这是函数返回值设计的最重要原因之一,只是出了函数体,这个地址指向的内存空间“并不存在”了(可能被回收,可能被其它程序占用)。
所以当你再次去访问时,不仅编译过程中会警告你,甚至报错,即使你侥幸运行起来,也会弹出内存不可访问的错误。
热心网友
时间:2023-09-17 14:52
详细讲起来很复杂,我给你找到一个文章:
http://blog.csdn.net/newman0708/archive/2009/08/02/4401983.aspx
你自己仔细体会吧.
参考资料:http://blog.csdn.net/newman0708/archive/2009/08/02/4401983.aspx