论坛
潜水/灌水快乐,沉淀知识,认识更多同行。
ToB圈子
加入IT圈,遇到更多同好之人。
朋友圈
看朋友圈动态,了解ToB世界。
ToB门户
了解全球最新的ToB事件
博客
Blog
排行榜
Ranklist
文库
业界最专业的IT文库,上传资料也可以赚钱
下载
分享
Share
导读
Guide
相册
Album
记录
Doing
搜索
本版
文章
帖子
ToB圈子
用户
免费入驻
产品入驻
解决方案入驻
公司入驻
案例入驻
登录
·
注册
只需一步,快速开始
账号登录
立即注册
找回密码
用户名
Email
自动登录
找回密码
密码
登录
立即注册
首页
找靠谱产品
找解决方案
找靠谱公司
找案例
找对的人
专家智库
悬赏任务
圈子
SAAS
IT评测·应用市场-qidao123.com
»
论坛
›
物联网
›
物联网
›
Effective C++ 规则49:了解 new-handler 的行为 ...
Effective C++ 规则49:了解 new-handler 的行为
瑞星
金牌会员
|
2025-1-26 13:37:48
|
显示全部楼层
|
阅读模式
楼主
主题
990
|
帖子
990
|
积分
2970
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要
登录
才可以下载或查看,没有账号?
立即注册
x
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-handler
std::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-handler
static void setNewHandler(std::new_handler p) noexcept {
currentHandler = p;
}
// 重载 operator new,使用类专属的 new-handler
static 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); // 恢复旧的 handler
throw; // 继续抛出异常
}
std::set_new_handler(oldHandler); // 恢复旧的 handler
return 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 的关键。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复
使用道具
举报
0 个回复
倒序浏览
返回列表
快速回复
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
or
立即注册
本版积分规则
发表回复
回帖并转播
回帖后跳转到最后一页
发新帖
回复
瑞星
金牌会员
这个人很懒什么都没写!
楼主热帖
复习一下Linux常用命令,孰能生巧~ ...
OpenSSL RSA相关基本接口和编程示例 ...
2022护网面试题总结
一次服务器被入侵的处理过程分享 ...
使用 Power Shell 修改 Hyper-V 虚拟机 ...
适用于顺序磁盘访问的1分钟法则 ...
内网安全-横向移动(1)
Iceberg在袋鼠云的探索及实践 ...
Oracle实现金额小写转大写函数 ...
kubernetes入门
标签云
AI
运维
CIO
存储
服务器
浏览过的版块
分布式数据库
DevOps与敏捷开发
Oracle
鸿蒙
程序人生
网络安全
.Net
Java
快速回复
返回顶部
返回列表