Effective C++(了解new-handler的行为)


author:

  • luixiao1223
    title: 了解new-handler的行为

tips

STL 的heap时容器所拥有的分配器对象管理的,不是new和delete管理.

什么是new-handler

new抛出一场以反映一个未获满足的内存需求之前,会先调用一个用户指定的错误处理函数.这个就是new-handler.

namespace std {
    typedef void (*new_handler)();
    new_handler set_new_handler(new_handler p) throw();
}

比如你可以这样使用

void outOfMem()
{
    std::cerr << "Unable to satisfy request for memory\n";
    std::abort();
}

int main()
{
    std::set_new_handler(outOfMem);
    int *pBigDataArray = new int[100000000L];
}

当new无法满足内存申请时,他会不断调用new-handler函数
那么一个良好的new-handler应该具备

  1. 让更多的内存可被利用
  2. 安装另一个new-handler应该
  3. 写在new-handler
  4. 抛出 bad_alloc 会被抛出到外面
  5. 不反回,直接调用abort和exit

应用

我们想让不同的class具有不同的内存处理方式.我们需要class自己来定义自己的new
operator.那么标准的操作为.

  1. 设置handler
  2. new操作
  3. 恢复现场
class Widget {
public:
    static std::new_handler set_new_handler(std::new_handler p) throw();
    static void* operator new(std::size_t size) throw(std::bad_alloc);
private:
    static std::new_handler currentHandler;
};

std::new_handler Widget::currentHandler = 0;

std::new_handler Widget::set_new_handler(std::new_handler p) throw()
{
    std::new_handler oldHandler = currentHandler;
    currentHandler = p;
    return oldHandler;
}

Handler Holder

class NewHandlerHolder {
public:
    explicit NewHandlerHolder(std::new_handler nh)
        : handler(nh) {}
    ~NewHandlerHolder()
    { std::set_new_handler(handler); }
private:
    std::new_handlerhandler;
    NewHandlerHolder(const NewHandlerHolder&);
    NewHandlerHolder&
    operator=(const NewHandlerHolder&);
};

定义自己的new operator

void* Widget::operator new(std::size_t size) throw(std::bad_alloc)
{
    NewHandlerHolder
        h(std::set_new_handler(currentHandler));
    return ::operator new(size); //调用全局的new
    // 由于使用了 NewHandlerHolder ,这句之后将进行恢复现场.
}

使用的方法为

void outOfMem();
Widget::set_new_handler(outOfMem);Widget *pw1 = new Widget;
std::string *ps = new std::string;
Widget::set_new_handler(0);
Widget *pw2 = new Widget;

一个更好的版本,使用继承

template<typename T>
class NewHandlerSupport {
public:
    static std::new_handler set_new_handler(std::new_handler p) throw();
    static void* operator new(std::size_t size) throw(std::bad_alloc);
private:
    static std::new_handler currentHandler;
};


template<typename T>
std::new_handler
NewHandlerSupport<T>::set_new_handler(std::new_handler p) throw()
{
    std::new_handler oldHandler = currentHandler;
    currentHandler = p;
    return oldHandler;
}
template<typename T>
void* NewHandlerSupport<T>::operator new(std::size_t size)
    throw(std::bad_alloc)
{
    NewHandlerHolder h(std::set_new_handler(currentHandler));
    return ::operator new(size);
}

template<typename T>
std::new_handler NewHandlerSupport<T>::currentHandler = 0;

这样每一个不同的class都有自己独一无二的holder.
这正式T的作用.我们虽然没有使用到T,但是T使得我们有了独一无二的holder.

class Widget: public NewHandlerSupport<Widget> {
}; //Widget继承自一个模板,这个模板的类型参数为Widget.也就是它自己.

One More Thing

class Widget { ... };

Widget *pw1 = new Widget;

if (pw1 == 0)
    ...
Widget *pw2 = new (std::nothrow) Widget;

if (pw2 == 0)
    ...

其实不抛出异常是不可能的.但是你使用std::nothrow只是保证第一层new不抛出异常.失败就返回null.但是Widget的构造函数里面可能也会进行new操作这里面的异常抛出行为就不会受到你的控制.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: default-servlet-handler是Spring MVC框架中的一个处理器,用于处理静态资源请求。当请求的URL没有匹配到任何一个Controller时,default-servlet-handler会将请求转发给Servlet容器中的默认Servlet来处理,例如Tomcat中的DefaultServlet。这样可以避免在Controller中处理静态资源请求,提高系统性能。 ### 回答2: default-servlet-handler是Spring MVC框架用于处理静态资源的默认处理器,它是一个处理器映射器和处理器适配器的组合。在Spring MVC中,当发送来自客户端的静态文件请求时,会使用该default-servlet-handler默认处理器来处理这些请求。 Spring MVC的默认处理器使用了Servlet容器的默认Servlet来处理静态资源的请求。这些静态资源可以是图片、CSS文件、JavaScript文件或HTML文件等。当请求的资源在内存中不存在时,default-servlet-handler会把请求转发到Servlet容器里的默认Servlet,由其来处理,并把处理结果返回给客户端。这样做可以减轻Spring MVC本身的负担,提高整个应用程序的性能。 使用default-servlet-handler,我们可以不必为所有静态资源创建控制器,以提高应用程序启动和运行速度。这就是说,当我们的控制器无法处理一个请求时,Spring MVC会检查是否有默认的Servlet来处理这个请求,并把这个请求转给该Servlet。所以,我们可以通过在web.xml文件中注册Servlet来实现对不同路径的映射和处理。 另外需要注意的是,default-servlet-handler在XML配置文件中的配置代码如下: ```xml <mvc:default-servlet-handler/> ``` 在注解配置中的代码如下: ```java @Configuration @EnableWebMvc public class AppConfig implements WebMvcConfigurer { @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } } ``` 以上就是default-servlet-handler的基本使用和配置方法。如果在Spring MVC框架中需要处理静态资源并提高应用程序的性能,这个处理器的使用是非常值得推荐的。 ### 回答3: default-servlet-handler是Spring框架中的一个组件,它是用来处理静态资源(如图片、CSS文件、JavaScript文件等)的一个处理器。在Web应用程序中,通常会有很多静态资源需要提供给客户端访问,如何高效地管理这些资源并提供访问? 在传统的Web应用程序中,通常会将静态资源放在Web服务器的某个目录下,如Tomcat中的【webapps】目录。Web服务器收到客户端请求后,根据URL去服务器中查找对应的文件并返回给客户端。但是,这种方式存在一个问题:每次静态资源的修改都需要重启Web服务器,影响Web应用程序的正常运行。 而Spring框架中提供了default-servlet-handler能够解决这个问题,它会去解析Web应用程序中的资源和请求路径,并将请求转发到Web服务器的默认Servlet来处理。这样,Web服务器就不需要重启就可实时地提供静态资源。 default-servlet-handler的原理是将对静态资源的请求交给Web服务器中的默认Servlet来处理,而不是交给DispatcherServlet来处理。需要注意的是,default-servlet-handler只是用来处理静态资源,如果请求的URL路径与某些动态请求有冲突,则会由DispatcherServlet来处理动态请求。 在配置default-servlet-handler时,需要为该处理器指定一个URL模式,用于匹配静态资源的请求路径。例如: <mvc:default-servlet-handler /> 这样配置就会将所有静态资源请求交给Web服务器默认的Servlet来处理。 综上所述,default-servlet-handler是Spring框架中用于处理静态资源的重要组件,它能够高效地提供静态资源访问的服务,降低Web服务器重启频率,提高Web应用程序的稳定性和效率。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luixiao1220

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值