Chinaunix首页 | 论坛 | 博客
  • 博客访问: 215510
  • 博文数量: 89
  • 博客积分: 2531
  • 博客等级: 少校
  • 技术积分: 830
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-19 10:10
文章分类
文章存档

2011年(6)

2010年(26)

2009年(35)

2008年(22)

我的朋友
最近访客

分类: C/C++

2008-11-10 23:09:49

很多时候,管理内存就是每个编程的人头疼的事情(可能python等等语言除外),在c++里尤为如此。如果我们在某个地方使用了new,我们一定会在接下来得编程过程里一直惴惴不安,因为我们太担心内存分配带来得问题了,虽然异常机制能带来一定的解决方法,但有时候我们也不是那么放心,毕竟有的异常是捕捉不到的,所以有一种机制很又用武之地。  我们希望能在内存分配失败得时候能做点什么,而不是仅仅抛出一个异常,然后abort(),这不过是暂时转移了注意得意思而已。
  比如,如果我们申请了一个很大得内存空间,但是分配失败了,这个时候我们希望程序能继续尝试着分配直到分配成功或者确实没有空间而失败,于是我们用到了new_handler()这个函数,这个函数是定义在头文件中,他的定义类似
typedef void (*new_handler)();//错误处理函数
new_handler set_new_handler(new_handler p)throw();
我么来看这样的一个定义是什么意思?首先从typedef得语法我们直到new_handler是一个指向函数得指针,这个被指向得函数不返回任何值,也不接受任何得参数。而set_new_handler(new_handler p)是一个返回值是new_handler并且接受一个new_handler参数得函数,这个函数的行为很有意思,他会保存传入得new_handler p的值,而返回之前得旧的错误处理函数,之后我们会看到如果要在class里实现new_handler的话我们就要模仿这个性质。好了介绍完了,我们来看看怎么使用他们。

void handlerror()
{
    cerr<<”bad_alloc!”;
   abort();
}
int p = new int(100000000000);//分配失败

set_new_handler(handlerror);

假如operator new不能为100000000000个整数分配空间,handlerror()将会被调用,程序发出一条出错信息后终止,operator new不能满足内存分配请求时,new-handler函数不只调用一次,而是不断重复,直至找到足够的内存,非常漂亮.
  c++是不支持专门对类的new_handler函数的,但是我们可以自己定义,当我们在class内用operator new分配失败时,我们就可以调用我们希望用得错误处理函数,由于每次都要调用出错处理函数,把他声明为静态成员函数是应该的。我们得类就会是这样了

class exm
{
public:
     static new_handler set_new_handler(new_handler p);
     static void* operator new(size_t size);
private:
     static new_handler currenthandler;
};

exm:: currenthandler需要在类外部定义,我们可以把他初始化为null
exm:: currenthandler = NULL;
现在我们要来模仿标准得set_new_handler()函数得行为了

new_handler exm::set_new_handler(new_handler p)
{
    new_handler oldhandler = currenthandler;
   currenthandler = p;
   return oldhandler;
}

现在要来看看类exm得operator new要做什么了。
第一要尝试分配内存,失败的话就要调用exm的错误处理函数,这个时候得错误处理函数是全局得new_handler,如果分配还是失败得话,就抛出一个std::bad_alloc异常。exm的operator new会捕捉到它。exm的operator new然后恢复最初被取代的全局new_handler函数,最后以抛出异常返回。
所以是这样得

void* exm::operator new(size_t size)
{
    //安装new_handler,成为全局得new_handler

    new_handler globlehandler = std::set_new_handler(currenthandler);
    void* memory;
    //尝试分配

   try{
   memory = ::operator new(size);
   }catch(std::bad_alloc&){
   std::set_new_handler(globlehandler);//回复原来得错误处理函数

   throw();
}
  std::set_new_handler(globalhandler); // 恢复原来的new_handler

return memory;
}

是不是觉得没有提心吊胆得感觉了呢?

阅读(1954) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~