我想处理我的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 宏??
感谢。
答案 0 :(得分:8)
您正在寻找堆栈跟踪,并且没有可移植的方式来获取它。可以通过以下方式实现类似的功能:
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检测的函数或位置)。如果仅在测试期间(而不是在生产中)需要这样做,那么您可能应该只启用核心转储并学习如何在事后分析中运行调试器。
答案 1 :(得分:1)
C行几乎是不可能的(我想不出办法......除非将第二个参数传递给f
,__LINE__
。
A行如下:
void f(int i){ const int lineA = __LINE__;
if(i<0)
throw(OutOfRange("message", __LINE__); // LINE B
}
答案 2 :(得分:1)
您需要堆栈跟踪和调试器。在标准C ++中,您无法在不将其作为参数(f(-6, __LINE__)
)传递的情况下找到行C,并且根本无法找到行A.
答案 3 :(得分:1)
CPPUNit框架使用宏而不是函数。这样,您可以轻松地在调用宏的同一位置获取行号。
我不认为这是一般意义上的有效方法,但您可能会发现看看CPPUnit开发人员的方式很有意思。
答案 4 :(得分:0)
除了__LINE__
,您还可以使用__func__
和__FILE__
为您提供更多信息。
__func__
将为您提供A行,并且您至少可以通过从那里重新抛出来在catch
块内获得一条行,但是我不知道另一种获得C行的方法。
这可能会帮助您使用标准C ++ 11 创建回溯,即跨平台且无需调试器或繁琐的日志记录。 自问这个问题以来的几年中,一些有用的功能已添加到C ++。 您可以使用以下方法跟踪导致异常的调用堆栈:
std::nested_exception
和std::throw_with_nested
在StackOverflow here和here上进行了描述
但是,这将要求您在要跟踪的功能上插入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"