错误报告知道它在代码中的位置

时间:2011-09-15 12:32:46

标签: c++ c-preprocessor

我有一个名为“err”的流,它位于命名空间Errors中。这就是开发人员如何以用户友好的方式报告错误。因此,当出现问题时,开发人员将编写错误消息:

Errors::err << "Oh no. That was a bad thing.";

是否可以使用预处理器将[__FILE__:__LINE__]附加到错误消息中而不更改当前的错误报告样式?即现在上面的命令(在预处理魔术之后)将其输出到错误文件:

  

哦不。那是件坏事。 [file.cc:20]

我自己试过这个,但 C 预处理器似乎不喜欢命名空间,我觉得我不能在代码中的任何地方替换“错误” - 这将是一个如果开发人员决定使用using Errors::errusing namespace Errors,则更大的问题。

在我想要实现的范围内,C-Preprocessor是否与编码风格根本不兼容?如果有的话还有其他任何方法(可能是基于Makefile的吗?)来做我想做的事情吗?

2 个答案:

答案 0 :(得分:5)

对于您目前的风格,这是不可能的。在运行时调用的例程不知道谁调用它们。但是,你可以obtain the backtrace using platform-specific functions写下来。

如果您可以替换所有错误报告代码,例如。与

REPORT_ERROR( "Oh no. That was a bad thing." );
这很容易。你只需#define

#define REPORT_ERROR(x) Errors::err << x << "[" << __FILE__ << ":" << __LINE__ << "]" << endl;

答案 1 :(得分:4)

在这里,我认为这有效。你应该注意到这样做可能是一个坏主意,因为这段代码充其量只是时髦,完全错误或最坏无效。我没有真正测试或检查过这个,但我知道它在我的系统上编译并运行(Windows 7 / MSVC10)。如果我在生产代码中看到类似的东西,我可能会认为这是一个黑客攻击,否则必须说服。

享受。

#include <cstdlib>
#include <sstream>
#include <string>
#include <iostream>
using namespace std;

namespace Errors
{
    class errstream
    {
    public:
        errstream(const std::string& filename, int lineno) : file_(filename), line_(lineno) {};
        std::string dump() const;
        errstream& operator<<(const std::string& msg)
        {
            cout << msg << "\t[" << file_ << ":" << line_ << "]";
            return * this;
        }
    private:
        std::string file_;
        int line_;
    };
};

 #define err errstream(__FILE__, __LINE__)

int main()
{
    Errors::err << "Oh no. That was a bad thing.";
}

输出是(对我来说):

  

哦不。那是件坏事。 [main.cpp中:30]

编辑:第2轮

在下面的评论中,提出了新的要求。 OP希望能够做到这样的事情:

Errors::err << "File Not Found '" << file << "'  What A Bummer. :(";

...并输出为:

  

找不到档案! 'foo.txt'多么糟糕。 :([file:nnn]

我的原始代码不会产生此输出,因为它只能为该位置添加一个附加标记来处理多个流插入。输出反而成了一大堆:

  

找不到档案! '[main.cpp:61] foo.txt [main.cpp:61]'真是太棒了   无赖。 :( [main.cpp:61]

当调用析构函数时,errstream将其内容转储到cout,而不是在调用流插入运算符时,可以容纳这种情况。反过来,流插入操作员会收集将在位置字符串之前转储到cout的令牌。新代码:

#include <cstdlib>
#include <sstream>
#include <string>
#include <iostream>
#include <iterator>
#include <vector>
using namespace std;

namespace Errors
{
    class errstream
    {
    public:
        errstream(const std::string& filename, int lineno) : file_(filename), line_(lineno) {};
        ~errstream()
        {
            std::copy(tokens_.begin(), tokens_.end(), ostream_iterator<string>(cout));
            cout << "\t[" << file_ << ":" << line_ << "]\n";
        }
        errstream& operator<<(const std::string& msg)
        {
            tokens_.push_back(msg);
            return *this;
        }
    private:
        typedef std::vector<std::string> Tokens;
        Tokens tokens_;
        std::string file_;
        int line_;
    };
};

 #define err errstream(__FILE__, __LINE__)

int main()
{
    Errors::err << "Oh no. That was a bad thing.";

    string file = "foo.txt";
    Errors::err << "File not found! '" << file << "' What a bummer. :(";

}

输出现在是:

  

哦不。那是件坏事。 [main.cpp:38]

     

找不到档案! 'foo.txt'多么糟糕。 :( [main.cpp:41]