You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++如何在catch块中获取系统异常发生的代码行号

C++ catch块获取异常发生行号的方案

结论先行

标准C的默认std::exception异常类型没有内置存储源代码位置信息,你给出的示例代码中直接捕获exception的场景,无法直接拿到异常触发的Line2行号。
如果需要实现这个能力,需要自定义异常类结合编译器内置宏或C
20标准特性实现,具体方案如下:

实现方案

方案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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 00:54:03