当前位置: 首页 > news >正文

Effective C++ 规则49:了解 new-handler 的行为

1、背景

在 C++ 中,new 运算符用于动态分配内存。然而,当内存分配失败时,程序默认会抛出一个 std::bad_alloc 异常。为了更灵活地处理这种情况,C++ 提供了一种机制,允许开发者自定义内存分配失败时的行为。这就是 new-handler 机制的作用。new-handler 是一种回调函数,当 new 操作符无法分配内存时,运行时系统会调用这个回调函数。通过设置自定义的 new-handler,开发者可以在内存分配失败时执行一些特定的操作,例如:

  • 释放未使用的内存。
  • 记录错误日志。
  • 尝试再次分配内存。
  • 终止程序或采取其他恢复措施。
    new-handler 的设计使程序能够优雅地应对内存分配失败,而不是直接崩溃。

2、如何使用new-handler

C++ 提供了两个与 new-handler 相关的标准函数:

  • std::set_new_handler,用于设置全局的 new-handler 函数,定义在头文件 中。
  • std::new_handler,是一个函数指针,指向当前的 new-handler,以下是 std::set_new_handler 的函数签名:
#include <new>
std::new_handler std::set_new_handler(std::new_handler new_p) noexcept;
  • 参数:new_p 是指向新的 new-handler 函数的指针。
  • 返回值:返回之前设置的 new-handler。
  • 异常保证:此函数不抛出任何异常。

3、示例代码

以下是一个完整示例,展示如何使用 std::set_new_handler 设置自定义的 new-handler。

#include <iostream>
#include <new> // std::set_new_handler
#include <cstdlib> // std::abort// 自定义 new-handler 函数
void myNewHandler() {std::cerr << "Memory allocation failed. Attempting to recover..." << std::endl;// 可以选择释放资源或记录日志// 示例:直接终止程序std::abort();
}int main() {// 设置全局的 new-handlerstd::set_new_handler(myNewHandler);try {// 故意尝试分配超大内存size_t size = static_cast<size_t>(-1);int* p = new int[size];delete[] p;} catch (const std::bad_alloc& e) {std::cerr << "Caught exception: " << e.what() << std::endl;}return 0;
}

输出结果:Memory allocation failed. Attempting to recover…
因为,当 new 运算符无法分配内存时,运行时调用了自定义的 myNewHandler,打印错误信息并终止程序。如果未设置 new-handler,程序默认会抛出 std::bad_alloc 异常。
有时,我们可能希望为某个特定的类设置专属的 new-handler,而不是全局生效。这可以通过类的静态成员函数实现,代码如下:

#include <iostream>
#include <new>
#include <cstdlib>class Widget {
public:// 设置类专属的 new-handlerstatic void setNewHandler(std::new_handler p) noexcept {currentHandler = p;}// 重载 operator new,使用类专属的 new-handlerstatic void* operator new(size_t size) {std::new_handler oldHandler = std::set_new_handler(currentHandler);void* mem;try {mem = ::operator new(size);} catch (...) {std::set_new_handler(oldHandler); // 恢复旧的 handlerthrow; // 继续抛出异常}std::set_new_handler(oldHandler); // 恢复旧的 handlerreturn mem;}private:static std::new_handler currentHandler;
};// 定义静态成员
std::new_handler Widget::currentHandler = nullptr;// 自定义 new-handler
void customNewHandler() {std::cerr << "Widget allocation failed. Cleaning up..." << std::endl;std::abort();
}int main() {Widget::setNewHandler(customNewHandler);try {// 尝试分配超大内存Widget* w = new Widget[static_cast<size_t>(-1)];delete[] w;} catch (const std::bad_alloc& e) {std::cerr << "Caught exception: " << e.what() << std::endl;}return 0;
}

4、使用new-handler的注意事项

  • 确保 new-handler 是无异常的:new-handler 必须是 noexcept 函数。如果 new-handler 抛出异常,标准库会调用 std::terminate。
  • 处理恢复逻辑:在 new-handler 中,尝试释放未使用的内存或其他资源,尽量避免直接终止程序。
  • 避免递归调用:如果在 new-handler 中尝试再次分配内存,可能导致递归调用 new-handler,最终导致程序崩溃。
  • 线程安全性:std::set_new_handler 会影响全局的 new-handler,因此在多线程环境下使用时需要格外小心。

5、总结

new-handler 是 C++ 提供的一种强大的机制,允许开发者在内存分配失败时定制处理逻辑。通过全局或类专属的 new-handler,程序可以优雅地应对内存不足的情况。尽管如此,new-handler 的使用需要谨慎。合理地释放资源、避免递归调用以及处理异常是实现一个可靠 new-handler 的关键。

相关文章:

Effective C++ 规则49:了解 new-handler 的行为

1、背景 在 C 中&#xff0c;new 运算符用于动态分配内存。然而&#xff0c;当内存分配失败时&#xff0c;程序默认会抛出一个 std::bad_alloc 异常。为了更灵活地处理这种情况&#xff0c;C 提供了一种机制&#xff0c;允许开发者自定义内存分配失败时的行为。这就是 new-han…...

头像生成小程序搭建(免费分享)

如下图为小程序页面的基本效果&#xff0c;下面将介绍该小程序的功能 页面template代码如下&#xff1a; <template><view class"avatar-containner"><block v-if"!showCropper"><image class"pageback" src"../../s…...

手撕Diffusion系列 - 第九期 - 改进为Stable Diffusion(原理介绍)

手撕Diffusion系列 - 第九期 - 改进为Stable Diffusion&#xff08;原理介绍&#xff09; 目录 手撕Diffusion系列 - 第九期 - 改进为Stable Diffusion&#xff08;原理介绍&#xff09;DDPM 原理图Stable Diffusion 原理Stable Diffusion的原理解释Stable Diffusion 和 Diffus…...

MySQL 基础学习(2): INSERT 操作

在这篇文章中&#xff0c;我们将专注于 MySQL 中的 INSERT 操作&#xff0c;深入了解如何高效地向表中插入数据&#xff0c;并探索插入操作中的一些常见错误与解决方案。 一、基础 INSERT 语法 在 MySQL 中&#xff0c;INSERT 操作用于向表中插入新记录&#xff0c;基本语法如…...

openstack 客户端命令行简介

openstack 客户端命令行简介 基本用法常用命令分类**身份认证&#xff08;Keystone&#xff09;**常用命令 **计算服务&#xff08;Nova&#xff09;**常用命令&#xff1a; **网络服务&#xff08;Neutron&#xff09;**常用命令&#xff1a; **块存储服务&#xff08;Cinder&…...

Oracle查看数据库表空间使用情况

Oracle RAC环境查看表空间使用情况 查询字段释义&#xff1a; NEED_ADDFILE,--是否需增加表空间文件 TABLESPACE_NAME,--表空间名称 TABLESPACE_FILE_COUNT, --表空间当前数据文件数量 NOW_FILEENABLE_BLOCKS,--表空间文件当前数据块数 NOW_FILEENABLE_BYTES_GB,--表空间文件当…...

[护网杯 2018]easy_tornado1

题目 、 依次点击文件查看 /flag.txt flag in /fllllllllllllag /welcome.txt render /hints.txt md5(cookie_secretmd5(filename)) tornado模板注入 报cookie /error?msg{{handler.settings}} cookie_secret: 6647062b-e68d-4406-90d3-06e307fa955c} 使用python脚本…...

关于java实现word(docx、doc)转html的解决方案

最近在研究一些关于文档转换格式的方法&#xff0c;因为需要用在开发的一个项目上&#xff0c;所以投入了一些时间&#xff0c;给大家聊下这块逻辑及解决方案。 一、关于word转换html大致都有哪些方法&#xff1f; &#xff08;1&#xff09;使用 Microsoft Word 导出 其实该…...

【8】思科IOS AP升级操作

1.概述 本文主要针对思科AP的升级操作进行记录,思科的AP目前主要分为IOS和COS AP,IOS AP是我们常见的AP3502/AP1602/AP2702等等型号的AP,而COS AP是AP2802/3802等型号的AP。当然这里所指的都是一些室内AP,如AP1572等室外AP也同样适用。本文先对IOS AP的升级操作进行总结,…...

【ROS2】RViz2界面类 VisualizationFrame 详解

1、简述 VisualizationFrame 继承自 QMainWindow 和 WindowManagerInterface; 窗口顶部是常规布局:菜单栏 和 工具栏 窗口中心是 RenderPanel,用来渲染3D画面 周围是dock区域,包括:DisplaysPanel、ViewsPanel、TimePanel、SelectionPanel 和 ToolPropertiesPanel Windo…...

2025年01月24日Github流行趋势

项目名称&#xff1a;shadPS4 项目地址url&#xff1a;https://github.com/shadps4-emu/shadPS4项目语言&#xff1a;C历史star数&#xff1a;15576今日star数&#xff1a;653项目维护者&#xff1a;georgemoralis, psucien, squidbus, raphaelthegreat, DanielSvoboda项目简介…...

Gradle buildSrc模块详解:集中管理构建逻辑的利器

文章目录 buildSrc模块二 buildSrc的使命三 如何使用buildSrc1. 创建目录结构2. 配置buildSrc的构建脚本3. 编写共享逻辑4. 在模块中引用 四 典型使用场景1. 统一依赖版本管理2. 自定义Gradle任务 3. 封装通用插件4. 扩展Gradle API 五 注意事项六 与复合构建&#xff08;Compo…...

【Airsim 仿真】查找配置文件 settings json 的路径优先级

Airsim 查找配置文件 settings.json 的路径优先级 参考官方文档 Settings - AirSim 文件格式要求 settings.json 文件采用常规的 JSON 格式。在首次启动时&#xff0c;AirSim 会在用户的主文件夹中创建一个没有设置的 settings.json 文件&#xff08;待测试&#xff09;。为…...

【FreeRTOS 教程 四】队列创建与发布项目到队列

目录 一、FreeRTOS队列&#xff1a; &#xff08;1&#xff09;队列介绍&#xff1a; &#xff08;2&#xff09;用户模型说明&#xff1a; &#xff08;3&#xff09;阻塞队列&#xff1a; 二、队列管理 API&#xff1a; &#xff08;1&#xff09;uxQueueMessagesWaiti…...

STM32项目分享:智能厨房安全检测系统

目录 一、前言 二、项目简介 1.功能详解 2.主要器件 三、原理图设计 四、PCB硬件设计 PCB图 五、程序设计 六、实验效果 七、资料内容 项目分享 一、前言 项目成品图片&#xff1a; 哔哩哔哩视频链接&#xff1a; STM32智能厨房安全检测系统 &#xff08;资料分…...

2025美赛数学建模MCM/ICM选题建议与分析,思路+模型+代码

2025美赛数学建模MCM/ICM选题建议与分析,思路模型代码&#xff0c;详细更新见文末名片 一、问题A&#xff1a;测试时间&#xff1a;楼梯的恒定磨损&#xff08;Archaeological Modeling&#xff09; 适合专业&#xff1a;考古学、历史学、数学、机械工程 难度&#xff1a;中等…...

高并发问题的多维度解决之道

‍‌​​‌‌​‌​‍‌​​​‌‌​​‍‌​​​‌​‌​‍‌​​‌​​‌​‍‌‌​​‌​‌​‍‌​‌​‌‌​​‍‌​‌​‌​​​‍‌​‌​‌​‌​‍‌​‌‌​​‌​‍‌​‌‌​​​​‍‌‌​​‌‌‌‌‍‌‌​​‌​‌‌‍‌​​​‌‌​​‍‌​​‌‌‌​​‍‌…...

Ubuntu环境 nginx 源码 编译安装

ubuntu 终端 使用 wget 下载源码 sudo wget http://nginx.org/download/nginx-1.24.0.tar.gz解压刚下载的源码压缩包 nginx-1.24.0.tar.gz sudo tar -zxvf nginx-1.24.0.tar.gz 解压完成 产生 nginx-1.24.0 目录 进入该目录 cd ./nginx-1.24.0 目录下有一个可执行文件 con…...

K8S中的数据存储之基本存储

基本存储类型 EmptyDir 描述&#xff1a;当 Pod 被调度到节点上时&#xff0c;Kubernetes 会为 Pod 创建一个空目录&#xff0c;所有在该 Pod 中的容器都可以访问这个目录。特点&#xff1a; 生命周期与 Pod 绑定&#xff0c;Pod 删除时&#xff0c;数据也会丢失。适用于临时…...

编码器和扩散模型

目录 摘要abstract1.自动编码器2.变分编码器&#xff08;VAE&#xff09;3.论文阅读3.1 介绍3.2 方法3.3 结论 4.总结参考文献 摘要 本周学习了自动编码器&#xff08;AE&#xff09;和变分自动编码器&#xff08;VAE&#xff09;的基本原理与实现&#xff0c;分析其在数据降维…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

OpenLayers 可视化之热力图

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 热力图&#xff08;Heatmap&#xff09;又叫热点图&#xff0c;是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

三分算法与DeepSeek辅助证明是单峰函数

前置 单峰函数有唯一的最大值&#xff0c;最大值左侧的数值严格单调递增&#xff0c;最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值&#xff0c;最小值左侧的数值严格单调递减&#xff0c;最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

多模态图像修复系统:基于深度学习的图片修复实现

多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...

破解路内监管盲区:免布线低位视频桩重塑停车管理新标准

城市路内停车管理常因行道树遮挡、高位设备盲区等问题&#xff0c;导致车牌识别率低、逃费率高&#xff0c;传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法&#xff0c;正成为破局关键。该设备安装于车位侧方0.5-0.7米高度&#xff0c;直接规避树枝遮…...