C++如何在catch块中获取系统异常发生的代码行号
C++ catch块获取异常发生行号的方案
结论先行
标准C的默认std::exception异常类型没有内置存储源代码位置信息,你给出的示例代码中直接捕获exception的场景,无法直接拿到异常触发的Line2行号。
如果需要实现这个能力,需要自定义异常类结合编译器内置宏或C20标准特性实现,具体方案如下:
实现方案
方案1:基于预定义宏(兼容所有C++标准)
利用编译器内置的__LINE__(当前行号)、__FILE__(当前文件名)、__func__(当前函数名)宏,配合抛异常的封装宏,把位置信息嵌入自定义异常对象中:
#include <exception> #include <string> #include <iostream> // 自定义带位置信息的异常类 class LocException : public std::exception { private: std::string err_msg; int line; std::string file; std::string func; public: LocException(const char* msg, int line, const char* file, const char* func) : line(line), file(file), func(func) { err_msg = std::string(file) + ":" + std::to_string(line) + "(" + func + "): " + msg; } const char* what() const throw() override { return err_msg.c_str(); } int get_line() const { return line; } const char* get_file() const { return file.c_str(); } const char* get_func() const { return func.c_str(); } }; // 封装抛异常的宏,自动注入位置信息 #define THROW_LOC_EXCEPTION(msg) throw LocException(msg, __LINE__, __FILE__, __func__) int main() { try { // Line 1 THROW_LOC_EXCEPTION("触发系统异常"); // 对应你示例里的Line2 // Line 3 } catch (const LocException& e) { std::cout << "异常发生位置:" << e.get_file() << " 第" << e.get_line() << "行,函数:" << e.get_func() << std::endl; std::cout << "异常信息:" << e.what() << std::endl; } catch (const std::exception& e) { // 处理其他标准异常 std::cout << "标准异常:" << e.what() << std::endl; } return 0; }
方案2:基于C++20 std::source_location(更优雅)
C++20新增了std::source_location类型,可以直接获取代码位置信息,不需要依赖宏定义:
#include <exception> #include <string> #include <iostream> #include <source_location> class LocException : public std::exception { private: std::string err_msg; std::source_location loc; public: LocException(const char* msg, std::source_location loc = std::source_location::current()) : loc(loc) { err_msg = std::string(loc.file_name()) + ":" + std::to_string(loc.line()) + "(" + loc.function_name() + "): " + msg; } const char* what() const throw() override { return err_msg.c_str(); } int get_line() const { return loc.line(); } const char* get_file() const { return loc.file_name(); } const char* get_func() const { return loc.function_name(); } }; int main() { try { // Line 1 throw LocException("触发系统异常"); // 对应你示例里的Line2,不需要额外传位置参数 // Line 3 } catch (const LocException& e) { std::cout << "异常发生位置:" << e.get_file() << " 第" << e.get_line() << "行,函数:" << e.get_func() << std::endl; } return 0; }
注意事项
- 上述方案仅对代码中主动抛出的异常生效,如果是内存访问越界、空指针解引用这类系统触发的硬件异常(也叫结构化异常,Windows下叫SEH),需要配合对应平台的异常捕获机制(Windows下用
__try/__except、Linux下用signal+backtrace)才能拿到位置信息。 - 生产环境编译如果开了O2优化、strip掉调试符号的话,运行时拿到的行号可能和源代码行号不一致,需要保留调试符号才能保证准确性。
内容的提问来源于stack exchange,提问作者Samson Petersingh
相关产品推荐
相关产品推荐

