[经验分享]对内存管理的理解,破除两个常见的迷思,初学者不妨看看。

野男孩 2009-03-05 09:19:11
理解内存管理的本质
http://blog.csdn.net/coding_hello/archive/2009/03/01/3947793.aspx

总听说不能在函数中返回局部变量的地址,那为什么下面的代码运行正常?

#include <stdio.h>
#include <string.h>

char* ReturnString(const char* szMsg)
{
char buf[3200] = {0};
strcpy(buf, szMsg);
return buf;
}

int main(void)
{
char* p = ReturnString("bad usage");
printf("%s\n", p);
return 0;
}


为什么有时候指针指向被释放了的内存,也照样能访问,能读能写。有时候一访问就出错,报什么0xC0000005错误。
...全文
304 42 打赏 收藏 转发到动态 举报
写回复
用AI写文章
42 条回复
切换为时间正序
请发表友善的回复…
发表回复
野男孩 2009-03-08
  • 打赏
  • 举报
回复
结贴了,兄弟们,楼上有些说没看明白的,建议在仔细看看,多调试。
Scofield_zao 2009-03-08
  • 打赏
  • 举报
回复
创天中文的会不会好一些呢~~~
zhuxueling 2009-03-08
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 sagegz 的回复:]
内存释放,但是指针的指向并没有改变...野指针!
[/Quote]

BS a.....
zhuxueling 2009-03-08
  • 打赏
  • 举报
回复
[Quote=引用 33 楼 liuysheng 的回复:]
引用楼主 coding_hello 的帖子:
理解内存管理的本质
http://blog.csdn.net/coding_hello/archive/2009/03/01/3947793.aspx
正常运行时,往往是在你开机不久时,这时的内存空间污染的不多,
所以,可能局部变量buf开始申请的空间一直没有作为它用,,,数据没有被改新...
而buf与p都是局部变量,并且在这个程序中只有这两个局部变量,都紧靠着存放在堆栈中,

当然,多数情况下,你这代码是会出错的...
特别是在好的编译器环境下...
[/Quote]

测试过没,你说正常情况下会出错?
哎。。。。
zhuxueling 2009-03-08
  • 打赏
  • 举报
回复
#include <stdio.h>

void helloworld(){
printf( "hello world.\n");
exit(0);
}

void fool(){
int *p = &p;
p[2] = (int)&helloworld;
}
int main(){
fool();
return 0;
}


这个地球上没有绝对的野指针。
不会用就直接说不会用好了。

这个程序在gcc下是会输出hello world的。
Scofield_zao 2009-03-08
  • 打赏
  • 举报
回复
我拿来运行了一下,运行通过~~~

但是还不理解其中的意义~~~

想知道VC++ 6.0企业版为什么不支持中文呢

凡是写中文的地方都是乱码~~~
过去的我 2009-03-08
  • 打赏
  • 举报
回复
stock888 2009-03-08
  • 打赏
  • 举报
回复
mark,学习一下
lhzl2001 2009-03-07
  • 打赏
  • 举报
回复
up
android2008 2009-03-07
  • 打赏
  • 举报
回复
up
野男孩 2009-03-07
  • 打赏
  • 举报
回复
自顶一下,明天来结贴散分。
野男孩 2009-03-07
  • 打赏
  • 举报
回复
如果你描述的就是你所理解的,那么我想你有必要更新一下你的理解。

这里出现的问题跟所谓的开机时间和内存空间污染并没有关系。

[Quote=引用 33 楼 liuysheng 的回复:]
正常运行时,往往是在你开机不久时,这时的内存空间污染的不多,
所以,可能局部变量buf开始申请的空间一直没有作为它用,,,数据没有被改新...
而buf与p都是局部变量,并且在这个程序中只有这两个局部变量,都紧靠着存放在堆栈中,

当然,多数情况下,你这代码是会出错的...
特别是在好的编译器环境下...
[/Quote]
liuysheng 2009-03-07
  • 打赏
  • 举报
回复
[Quote=引用楼主 coding_hello 的帖子:]
理解内存管理的本质
http://blog.csdn.net/coding_hello/archive/2009/03/01/3947793.aspx

总听说不能在函数中返回局部变量的地址,那为什么下面的代码运行正常?

C/C++ code
#include <stdio.h>
#include <string.h>

char* ReturnString(const char* szMsg)
{
char buf[3200] = {0};
strcpy(buf, szMsg);
return buf;
}

int main(void)
{
char* p …
[/Quote]
------------------------
正常运行时,往往是在你开机不久时,这时的内存空间污染的不多,
所以,可能局部变量buf开始申请的空间一直没有作为它用,,,数据没有被改新...
而buf与p都是局部变量,并且在这个程序中只有这两个局部变量,都紧靠着存放在堆栈中,

当然,多数情况下,你这代码是会出错的...
特别是在好的编译器环境下...
野男孩 2009-03-07
  • 打赏
  • 举报
回复
[Quote=引用 31 楼 yangch_nhcmo 的回复:]
建议把编译器警告开高点,这样的代码在我编译器上直接就报错,说返回了局部变量.
gcc 版本 4.3.2 20081105 (Red Hat 4.3.2-7) (GCC)
[/Quote]

编译器是警告你不要这么做,我要强调的是为什么不许这么做。
yangch_nhcmo 2009-03-07
  • 打赏
  • 举报
回复
[Quote=引用楼主 coding_hello 的帖子:]
理解内存管理的本质
http://blog.csdn.net/coding_hello/archive/2009/03/01/3947793.aspx

总听说不能在函数中返回局部变量的地址,那为什么下面的代码运行正常?
C/C++ code#include<stdio.h>#include<string.h>char*ReturnString(constchar*szMsg)
{charbuf[3200]={0};
strcpy(buf, szMsg);returnbuf;
}intmain(void)
{char*p=ReturnString("bad usage");
printf("%s\n", p);return0;
}

为什…
[/Quote]
建议把编译器警告开高点,这样的代码在我编译器上直接就报错,说返回了局部变量.
gcc 版本 4.3.2 20081105 (Red Hat 4.3.2-7) (GCC)

感谢楼主的分享!
jojotom 2009-03-07
  • 打赏
  • 举报
回复
学习了。。。
neeestth 2009-03-07
  • 打赏
  • 举报
回复
不错的帖子
lean 2009-03-07
  • 打赏
  • 举报
回复
mark
a88015056 2009-03-07
  • 打赏
  • 举报
回复
楼主的这个问题我前几天练习的编写返回指针的函数也曾遇到,下面也说下我在当中遇到的一些问题和最后的解决方案,一起学习。
一开始的时候是我想在子函数中声明一个指针变量。但是考虑到舒适化问题。我把它赋值为空了。然后就产生了第一个问题。不能对空指针进行赋值操作。因为空指针指向地址为0X00000000,此地址不允许被赋值,所以不能通过。后来,就希望进行自给分配内存来完成功能。结果功能确实也完成了。但是由于使用的是动态NEW分配,在函数末尾需要DELETE,结果就来了问题。因为我的RETURN总是在DELETE的前面。所以这个DELETE根本就没有起到作用,显然就存在内存泄露。而且这个函数中采用了递归调用。如果处理的数据规模很大的话那就非常糟糕了。最后就考虑到用布局NEW,在一个声明的全局数组中进行动态内存分配,这样不需要DELETE,也不会引起内存泄露。所以我觉得如果要使用或者编写返回指针的函数时候,最好使用以声明全局可变内存空间中进行动态分配。因为我也才学习不久,所以现在只知道这种解决的办法。下面是我写的那个函数。但是其中的全局内存是固定的。询问过老师。老师说STL中有VECTOR类可以进行动态分配。

#include <iostream>
#include <string>
using namespace std;

typedef struct node
{
char data;
struct node *lchild,*rchild;
}Jiedian;

char *Aarray = "abdecfg";//树的先序遍历
char *Barray = "debacgf";//树的中序遍历

static int count = 0;
Jiedian buffer[20];

Jiedian* find_root( const char* a,const char* b,int a_low,int a_high,int b_low,int b_high )
{
Jiedian *c = new ( buffer + count*sizeof(node) ) node;
if( b_high >= b_low )
{
if( b_high > b_low )
{
for( int i = 0;i <= b_high-b_low;i++ )
{
if( a[a_low] == b[b_low] )
{
c->data = a[a_low];
count++;
c->lchild = find_root( a,b,a_low+1,a_high,b_low+1,b_high );
c->rchild = NULL;
}
if( (a[a_low] == b[i+b_low])&&( i != 0 )&&( i+b_low != b_high ) )
{
c->data = a[a_low];
count++;
c->lchild = find_root( a,b,a_low+1,i+a_low,b_low,b_low+i-1 );
count++;
c->rchild = find_root( a,b,i+1+a_low,a_high,b_low+i+1,b_high );
}
if( a[a_low] == b[b_high] )
{
c->data = a[a_low];
c->lchild = NULL;
count++;
c->rchild = find_root( a,b,a_low+1,a_high,b_low,b_high-1 );
}
}
}
else if( b[b_low] == a[a_low] )
{
c->data = a[a_low];
c->lchild = NULL;
c->rchild = NULL;
}
return c;
}
else
{
cout << "two trees are different!";
return NULL;
}
}

void print( const Jiedian *c )
{
if( c != NULL )
{
print( c->lchild );
print( c->rchild );
cout << c->data ;
}
}

int main()
{

int len_A = strlen( Aarray );
int len_B = strlen( Barray );
if( len_A != len_B )
cout << "two trees are different!" << endl;
else
{
Jiedian *Tree = find_root( Aarray,Barray,0,len_A-1,0,len_B-1 );
print( Tree );
}

return 0;
}
zsf81 2009-03-07
  • 打赏
  • 举报
回复
瞅瞅
加载更多回复(22)

33,311

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 新手乐园
社区管理员
  • 新手乐园社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧