new的实现并模拟大多数编译器new失败机制

new的实现以及模拟set_new_handler机制

typedef void(*new_handler)( );

class x

{

public:

        static new_handler set_new_handler(new_handler p);

        static void* operator new(size_t size);

private:

        static new_handler currenthandler;

};

new_handler x::currenthandler = 0;

new_handler x::set_new_handler(new_handler p)

{

        new_handler oldhandler = currenthandler;

        currenthandler = p;

        return oldhandler;

}

void* x::operator new(size_t size)

{

        if (size = 0) {

               size = 1;

        }

        while (1) {

               void* result = malloc(size);

               if (result != NULL)           

                       return result;                //开辟成功,直接返回

               new_handler globalhandler = set_new_handler(0);       //把原先的保存

               set_new_handler(globalhandler);                             

               if (globalhandler)

                       (*globalhandler)();

               else

                       throw std::bad_alloc();

        }

}

重点是operator new

几乎很多现代的编译器默认都会这么做:

当我们int *p = new int[0];我们发现竟然成功。这是因为我们new默认如果参数是0的话,会以最小值分配

所以有

        if (size = 0) {

               size = 1;

        }

好了,当我们new分配到内存时,会返回我们分配的指针

               void* result = malloc(size);

               if (result != NULL)           

                       return result;                //开辟成功,直接返回

我们这里主要想说的是分配失败时,究竟编译器会做什么工作?

第一种情况:若然我们设置了set_new_handler函数,那么如何分配内存失败,就会去执行set_new_handler设置了的函数

我们可以看看set_new_handler大致是怎么实现的

new_handler x::set_new_handler(new_handler p)

{

        new_handler oldhandler = currenthandler;

        currenthandler = p;

        return oldhandler;

}

这个函数大致就是把新的设置进去,而把旧的返回出去,方便我们回收

回到operator new代码

               new_handler globalhandler = set_new_handler(0);       //把原先的保存

               set_new_handler(globalhandler);                             

               if (globalhandler)

                       (*globalhandler)();

               else

                       throw std::bad_alloc();

我们先获取set_new_handler里面的函数指针

去判断这个指针是否为NULL

若不为NULL,那就即是我们设置了set_new_handler

那么就去执行我们的set_new_handler

一般来说,set_new_handler该做的就是把一些我们没用的free掉,然后重新地去malloc

所以这里被写成了while(1)

第二种情况:

我们根本就没有设置set_new_handler

那么operator new就会抛出一个标准库的异常std::bad_alloc();

所以,我们若然抛出std::bad_alloc();而我们又不去处理,那么将会引出一个BUG

就是程序直接就死掉了

所以,我们应该在不同情况下去灵活地处理不同的事件

第一种方法:set_new_handler

第二种方法:try catch

第三种方法:重载operator new,重载我们的new操作(这个操作可移植性最高,因为STL在不同编译环境下都不同)

发布了23 篇原创文章 · 获赞 15 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/TanJiaLiang_/article/details/86600183