【原】函数返回指针,指向的内存谁来释放?

    好几年没用C/C++了,由于项目需要,重拾C/C++,使用中时不时的有种亲切感涌来。由于C/C++的自由,让人痛苦但更是让人喜欢的原因,一些经验和技巧显得尤为重要。

    最近总是想不明白,一个函数返回一个内存或者对象的指针,那么这个指针指向的对象(内存)到底由谁来释放?要知道,函数返回指针,通常是给外部临时使用的,其指向的内存通常由函数或者成员函数所在的对象自己来管理,其实就是遵从一个原则:自己的事自己做。

    如果返回一个函数中的临时变量地址,很显然,当执行return后,出了临时变量的作用区,变量将被销毁,这个指针指向的内存就被释放掉了,系统可能在任何时候修改它,这个指针实际变成了野指针,外部使用它是相当危险的;

    如果函数是个类的成员函数,我们能想到的是在对象中申明一个指针,由对象来管理它,成员函数只管使用,但问题是,如果有很多这样的函数,岂不是有很多这样的、只为函数存在的一些奇奇怪怪的指针?

    实际上,解决办法很简单——使用静态变量!——前面不是空了,而是白了,想看的,自己先想想答案,然后再想办法看吧 :0

来段代码:

 


//  取得Xml元素的值
//  itemName:元素名
//  buff:查找缓冲区
//  return:value字符串
char *  XmlPack::getElementValue( char *  itemName,  char *  buff)
{
    
static   char  value[ 64 ];

    
int  itemLen  =  strlen(itemName);

    
char *  itemStart  =   new   char [itemLen  +   3 ];
    memset(itemStart, 
' \0 ' , itemLen  +   3 );
    itemStart[
0 =   ' < ' ;
    itemStart[itemLen 
+   1 =   ' > ' ;
    strncpy(itemStart
+ 1 * sizeof ( char ), itemName, itemLen);

    
char *  itemEnd  =   new   char [itemLen  +   4 ];
    memset(itemEnd, 
' \0 ' , itemLen  +   4 );
    itemEnd[
0 =   ' < ' ;
    itemEnd[
1 =   ' / ' ;
    itemEnd[itemLen 
+   2 =   ' > ' ;
    strncpy(itemEnd
+ 2 * sizeof ( char ), itemName, itemLen);

    
char *  pos1  =  strstr(buff, itemStart);
    
if (pos1  !=  NULL)
    {
        pos1 
+=  strlen(itemStart);
        
char *  pos2  =  strstr(pos1, itemEnd);
        
if (pos2  !=  NULL)
        {
            assert((unsigned 
int )(pos2 - pos1) < sizeof (value));
            memset(value, 
' \0 ' sizeof (value));
            strncpy(value, pos1, pos2
- pos1);
            delete[] itemStart;
            delete[] itemEnd;
            
return  value;
        }
    }
    delete[] itemStart;
    delete[] itemEnd;
    
return  NULL;
}

 

     但是需要特别注意的是,使用局部静态变量是线程不安全的,是一个不可重入函数。

     解决这个问题的标准、权威的做法还是调用者提供存储空间,通过参数传入地址,这样,调用者可以使用局部变量来获取处理结果。这种方式麻烦,但是权威。下面一段文字来自Sun公司对多线程模型的讨论(《多线程编程指南》• 2006年10月,P231, 所有权归Sun公司所有):

 

引用 —— 《多线程编程指南》• 2006年10月,P231, 所有权归Sun公司所有

示例9–2 gethostbyname() 问题:

struct hostent *gethostbyname(char *name) {

static struct hostent result;
/* Lookup name in hosts database */
/* Put answer in result */
return(&result);
}
通常情况下,使用返回到局部变量的指针不是一个好办法。在本示例中使用指针有
效,是因为变量是静态的。但是,当两个线程同时使用不同的计算机名称调用此变量
时,使用静态存储会发生冲突。
与errno 问题一样,可以使用线程特定数据来替换静态存储。但是,此替换涉及到动态
分配存储,并且会增加调用开支。
处理该问题的更好方法是使gethostbyname() 的调用方为调用结果提供存储。调用方可
通过例程的其他输出参数来提供存储。其他输出参数需要gethostbyname() 函数的新接
口。
在线程中常使用此技术来解决许多问题。在大多数情况下,新接口的名称就是原有名
称附加"_r",如gethostbyname_r(3NSL)。

 

 

转载于:https://www.cnblogs.com/khler/archive/2010/09/23/1833458.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值