【问题标题】:how to get error line number in C++ program如何在 C++ 程序中获取错误行号
【发布时间】:2010-12-30 11:18:43
【问题描述】:

我想处理我的 c++ 程序中的错误,所以我创建了一些异常类来管理这些错误,但我想指定错误发生在程序的哪一行。

我将 LINE 宏传递给我的异常类的构造函数。

例如:

void f(int i){ // LINE A
  if(i<0)
    throw(OutOfRange("message", __LINE__); // LINE B
}

void main(){

  try{
    f(-6); // LINE C
  }
  catch(const OutOfRange& error){
    //do something
  }

}

在这个例子中我只能得到 LINE B 的号码,但我想得到 LINE A 和 LINE C 的号码。

任何想法,在哪里以及如何使用 LINE 宏??

谢谢。

【问题讨论】:

标签: c++ exception line


【解决方案1】:

您正在寻找堆栈跟踪,但没有可移植的方法来获取它。可以通过以下方式实现一些类似的东西:

struct SourcePoint
{
    const char *filename;
    int line;
    SourcePoint(const char *filename, int line)
      : filename(filename), line(line)
    { }
};

std::vector<SourcePoint> callstack;

struct SourcePointMarker
{
    SourcePointMarker(const char *filename, int line)
    {
        callstack.push_back(SourcePoint(filename, line);
    }

    ~SourcePointMarker()
    {
        callstack.pop_back();
    }
}

#define MARK_FUNCTION \
  SourcePointMarker sourcepointmarker(__FILE__, __LINE__);

然后在每个函数(或兴趣点)开始之后,您只需添加一行...例如

int myFunction(int x)
{
    MARK_FUNCTION
    ...
}

在您的错误处理程序中使用这种方法,您可以知道谁被谁调用等等(当然,您只会知道已使用 MARK_FUNCTION 检测的函数或位置)。如果仅在测试期间(而不是在生产中)需要这样做,那么您可能应该只启用核心转储并学习如何在事后分析中运行调试器。

【讨论】:

    【解决方案2】:

    您需要一个堆栈跟踪和一个调试器。在标准 C++ 中,如果不将 C 行作为参数传递 (f(-6, __LINE__)) 就无法找到 C 行,而且根本无法找到 A 行。

    【讨论】:

    • +1,但我会说“堆栈跟踪调试器”,因为即使没有外部调试器也可以获得堆栈跟踪(参见例如@987654322 @函数)。
    【解决方案3】:

    C 行几乎是不可能的(我想不出办法……除非将第二个参数传递给f__LINE__

    A行如下:

    void f(int i){ const int lineA = __LINE__;
      if(i<0)
        throw(OutOfRange("message", __LINE__); // LINE B
    }
    

    【讨论】:

    • 你的意思是 void f(int i){ const int lineA = LINE; if(i
    • 感谢您的回答,但我认为“LINE C”并非不可能,因为大多数编译器都使用它!
    • @CHAKRI:编译器可以做很多很多很多标准 C++ 做不到的事情。
    【解决方案4】:

    CPPUNit 框架使用宏而不是函数。这样您就可以轻松地在调用宏的同一位置获取行号。

    我认为这不是一般意义上的有效方法,但您可能会发现看看 CPPUnit 开发人员的做法会很有趣。

    【讨论】:

    • +1。查看 assert() 宏的实现;我创建了一个类似的 assertion() 宏,它抛出一个 std::logic_error 异常,而不是在断言失败时调用 std::abort()。
    【解决方案5】:

    除了__LINE__,您还可以使用__func____FILE__为您提供更多信息。 __func__ 会给你 A 行,你至少可以从那里重新抛出 catch-block 内的一行,但我不知道另一种方法来获得 C 行。


    它可能会帮助您使用 标准 C++11 创建回溯,即跨平台且无需调试器或繁琐的日志记录。 自从提出这个问题以来的几年里,C++ 中添加了一些有用的特性。 您可以使用以下方法跟踪导致异常的调用堆栈:

    std::nested_exceptionstd::throw_with_nested

    StackOverflow 上有描述 herehere

    但是,这将要求您在要跟踪的函数处插入 try/catch 语句(即,没有这个的函数将不会出现在您的跟踪中)。 您可以使用宏自动执行此操作,从而减少您必须编写/更改的代码量。

    由于您可以对任何派生的异常类执行此操作,因此您可以向此类回溯添加大量信息! 你也可以看看我的MWE on GitHub,回溯看起来像这样:

    Library API: Exception caught in function 'api_function'
    Backtrace:
    ~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
    ~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-08
      • 1970-01-01
      • 1970-01-01
      • 2016-08-24
      • 1970-01-01
      相关资源
      最近更新 更多