網站首頁 編程語言 正文
Boost.Exception 庫提供了一種新的異常類型 boost::exception,它允許您在拋出異常后將數據添加到異常中。此類型在 boost/exception/exception.hpp 中定義。由于 Boost.Exception 將其類和函數分布在多個頭文件中,以下示例訪問主頭文件 boost/exception/all.hpp 以避免一個接一個地包含頭文件。
Boost.Exception 支持 C++11 標準的機制,該機制將異常從一個線程傳輸到另一個線程。 boost::exception_ptr 類似于 std::exception_ptr。但是,Boost.Exception 并不能完全替代標準庫中的頭文件異常。例如,Boost.Exception 缺少對 std::nested_exception 類型的嵌套異常的支持。
注意
要使用 Visual C++ 2013 編譯本章中的示例,請刪除關鍵字 noexcept。此版本的 Microsoft 編譯器尚不支持 noexcept。
示例 56.1。使用 boost::exception
#include <boost/exception/all.hpp>
#include <exception>
#include <new>
#include <string>
#include <algorithm>
#include <limits>
#include <iostream>
typedef boost::error_info<struct tag_errmsg, std::string> errmsg_info;
struct allocation_failed : public boost::exception, public std::exception
{
const char *what() const noexcept { return "allocation failed"; }
};
char *allocate_memory(std::size_t size)
{
char *c = new (std::nothrow) char[size];
if (!c)
throw allocation_failed{};
return c;
}
char *write_lots_of_zeros()
{
try
{
char *c = allocate_memory(std::numeric_limits<std::size_t>::max());
std::fill_n(c, std::numeric_limits<std::size_t>::max(), 0);
return c;
}
catch (boost::exception &e)
{
e << errmsg_info{"writing lots of zeros failed"};
throw;
}
}
int main()
{
try
{
char *c = write_lots_of_zeros();
delete[] c;
}
catch (boost::exception &e)
{
std::cerr << boost::diagnostic_information(e);
}
}
Example56.1
示例 56.1 調用函數 write_lots_of_zeros(),該函數又調用 allocate_memory()。 allocate_memory() 動態分配內存。該函數將 std::nothrow 傳遞給 new 并檢查返回值是否為 0。如果內存分配失敗,則會拋出 allocation_failed 類型的異常。如果 new 分配內存失敗,allocation_failed 替換默認拋出的異常 std::bad_alloc 。
write_lots_of_zeros() 調用 allocate_memory() 以嘗試分配最大可能大小的內存塊。這是在 std::numeric_limits 的 max() 的幫助下完成的。該示例故意嘗試分配那么多內存以使分配失敗。
allocation_failed 源自 boost::exception 和 std::exception。不需要從 std::exception 派生類。 allocation_failed 也可以派生自不同類層次結構的類,以便將其嵌入現有框架中。雖然示例 56.1 使用標準定義的類層次結構,但僅從 boost::exception 派生 allocation_failed 就足夠了。
如果捕獲到 allocation_failed 類型的異常,allocate_memory() 必須是異常的來源,因為它是唯一拋出此類異常的函數。在有許多函數調用 allocate_memory() 的程序中,知道異常的類型不再足以有效地調試程序。在這些情況下,了解哪個函數試圖分配比 allocate_memory() 所能提供的更多的內存會有所幫助。
挑戰在于 allocate_memory() 沒有任何附加信息,例如調用者姓名,可以添加到異常中。 allocate_memory() 無法豐富異常。這只能在調用上下文中完成。
使用 Boost.Exception,可以隨時將數據添加到異常中。您只需為需要添加的每一位數據定義一個基于 boost::error_info 的類型。
boost::error_info 是一個需要兩個參數的模板。第一個參數是一個標簽,用于唯一標識新創建的類型。這通常是具有唯一名稱的結構。第二個參數是指存儲在異常中的值的類型。示例 56.1 定義了一個新類型 errmsg_info——通過結構 tag_errmsg 唯一標識——它存儲一個 std::string 類型的字符串。
在 write_lots_of_zeros() 的捕獲處理程序中,errmsg_info 用于創建一個用字符串“寫入大量零失敗”初始化的對象。然后使用 operator<< 將該對象添加到 boost::exception 類型的異常中。然后異常被重新拋出。
現在,異常不僅僅表示內存分配失敗。它還表示,當程序試圖在函數 write_lots_of_zeros() 中寫入大量零時,內存分配失敗。知道哪個函數稱為 allocate_memory() 可以更輕松地調試較大的程序。
要從異常中檢索所有可用數據,可以在 main() 的捕獲處理程序中調用函數 boost::diagnostic_information()。 boost::diagnostic_information() 為傳遞給它的每個異常調用成員函數 what() 并訪問存儲在異常中的所有附加數據。 boost::diagnostic_information() 返回一個 std::string 類型的字符串,例如,它可以寫入標準錯誤。
當使用 Visual C++ 2013 編譯時,示例 56.1 將顯示以下消息:
Throw location unknown (consider using BOOST_THROW_EXCEPTION)
Dynamic exception type: struct allocation_failed
std::exception::what: allocation failed
[struct tag_errmsg *] = writing lots of zeros failed
該消息包含異常類型、從 what() 檢索到的錯誤消息以及描述,包括結構名稱。
boost::diagnostic_information() 在運行時檢查給定異常是否源自 std::exception。 what() 只有在這種情況下才會被調用。
拋出 allocation_failed 類型異常的函數名稱未知。
Boost.Exception 提供了一個宏來拋出異常,該異常不僅包含函數名,還包含文件名和行號等附加數據。
示例 56.2。更多數據與 BOOST_THROW_EXCEPTION
#include <boost/exception/all.hpp>
#include <exception>
#include <new>
#include <string>
#include <algorithm>
#include <limits>
#include <iostream>
typedef boost::error_info<struct tag_errmsg, std::string> errmsg_info;
struct allocation_failed : public std::exception
{
const char *what() const noexcept { return "allocation failed"; }
};
char *allocate_memory(std::size_t size)
{
char *c = new (std::nothrow) char[size];
if (!c)
BOOST_THROW_EXCEPTION(allocation_failed{});
return c;
}
char *write_lots_of_zeros()
{
try
{
char *c = allocate_memory(std::numeric_limits<std::size_t>::max());
std::fill_n(c, std::numeric_limits<std::size_t>::max(), 0);
return c;
}
catch (boost::exception &e)
{
e << errmsg_info{"writing lots of zeros failed"};
throw;
}
}
int main()
{
try
{
char *c = write_lots_of_zeros();
delete[] c;
}
catch (boost::exception &e)
{
std::cerr << boost::diagnostic_information(e);
}
}
使用宏 BOOST_THROW_EXCEPTION 代替 throw,函數名、文件名和行號等數據會自動添加到異常中。但這僅在編譯器支持附加數據的宏時才有效。雖然 __FILE__ 和 __LINE__ 等宏自 C++98 以來就已標準化,但獲取當前函數名稱的宏 __func__ 僅在 C++11 中成為標準。由于許多編譯器在 C++11 之前提供了這樣的宏,BOOST_THROW_EXCEPTION 會嘗試識別底層編譯器并使用相應的宏(如果存在)。
使用 Visual C++ 2013 編譯,示例 56.2 顯示以下消息:
main.cpp(20): Throw in function char *__cdecl allocate_memory(unsigned int)
Dynamic exception type: class boost::exception_detail::clone_impl<struct boost::exception_detail::error_info_injector<struct allocation_failed> >
std::exception::what: allocation failed
[struct tag_errmsg *] = writing lots of zeros failed
在示例 56.2 中,allocation_failed 不再派生自 boost::exception。 BOOST_THROW_EXCEPTION 訪問函數 boost::enable_error_info(),它標識異常是否源自 boost::exception。如果不是,它會創建一個從指定類型和 boost::exception 派生的新異常類型。這就是為什么上面顯示的消息包含與 allocation_failed 不同的異常類型。
示例 56.3。使用 boost::get_error_info() 有選擇地訪問數據
#include <boost/exception/all.hpp>
#include <exception>
#include <new>
#include <string>
#include <algorithm>
#include <limits>
#include <iostream>
typedef boost::error_info<struct tag_errmsg, std::string> errmsg_info;
struct allocation_failed : public std::exception
{
const char *what() const noexcept { return "allocation failed"; }
};
char *allocate_memory(std::size_t size)
{
char *c = new (std::nothrow) char[size];
if (!c)
BOOST_THROW_EXCEPTION(allocation_failed{});
return c;
}
char *write_lots_of_zeros()
{
try
{
char *c = allocate_memory(std::numeric_limits<std::size_t>::max());
std::fill_n(c, std::numeric_limits<std::size_t>::max(), 0);
return c;
}
catch (boost::exception &e)
{
e << errmsg_info{"writing lots of zeros failed"};
throw;
}
}
int main()
{
try
{
char *c = write_lots_of_zeros();
delete[] c;
}
catch (boost::exception &e)
{
std::cerr << *boost::get_error_info<errmsg_info>(e);
}
}
Example56.3
示例 56.3 沒有使用 boost::diagnostic_information(),它使用 boost::get_error_info() 直接訪問 errmsg_info 類型的錯誤消息。因為 boost::get_error_info() 返回類型為 boost::shared_ptr 的智能指針,所以 operator* 用于獲取錯誤消息。如果傳遞給 boost::get_error_info() 的參數不是 boost::exception 類型,則返回空指針。如果宏 BOOST_THROW_EXCEPTION 始終用于拋出異常,則異常將始終從 boost::exception 派生——在這種情況下無需檢查返回的智能指針是否為 null。
原文鏈接:https://yamagota.blog.csdn.net/article/details/128031598
相關推薦
- 2022-06-01 Androidstudio調用攝像頭拍照并保存照片_Android
- 2022-10-31 解決Python3中二叉樹前序遍歷的迭代問題_python
- 2022-07-22 git倉庫的第一次上傳以及修改上傳項目
- 2024-01-27 DO、DTO、BO、VO、POJO區別
- 2022-05-17 【go】解決“dial tcp 142.251.42.241:443: connect: conne
- 2023-01-19 python全局解釋器GIL鎖機制詳解_python
- 2022-03-31 用C語言實現排雷游戲_C 語言
- 2022-10-18 C++中智能指針最常用的shared_ptr和unique_ptr_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支