开发者

Error reporting knowing where it is in the code

I have a stream called "err" which is in the namespace Errors. This is how the developer is meant to report errors in a user friendly way. So when something goes wrong the dev will write the error message as such:

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

Is it possible to use the preprocessor to append [__FILE__:__LINE__] to the error message without changing the current error reporting style? I.e. the above command开发者_如何学Go would now (after preprocessing magic) output this to an error file:

Oh no. That was a bad thing. [file.cc:20]

I have tried this myself, but the C Preprocessor doesn't seem to like namespaces, and I don't feel I can go replacing "err" everywhere in the code - which would be an even bigger issue if a dev decides to use using Errors::err or using namespace Errors.

In the scope of what I want to achieve, is the C-Preprocessor fundamentally incompatible with the coding style? If so are there any other methods (perhaps Makefile based?) to do what I wish?


This is impossible with your current style. The routines called at runtime don't know who calls them. You can, however, obtain the backtrace using platform-specific functions and write that.

If you could replace all error reporting code eg. with

REPORT_ERROR( "Oh no. That was a bad thing." );

it would be easy. You'd just #define the macro

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


Here you go, I think this works. You should note that doing this might be a bad idea, because this code is funky at best, downright faulty or invalid at worst. I haven't really tested or examined this deeply, but I know that it compiles and runs on my system (Windows 7/MSVC10). If I saw something like this in production code, I'd probably consider it a hack and would have to be convinced otherwise.

Enjoy.

#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.";
}

The output is (for me):

Oh no. That was a bad thing. [main.cpp:30]

EDIT: ROUND 2

In the comments below, a new requirement was stated. The OP wanted to be able to do something like this:

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

...and have the output be:

File not found! 'foo.txt' What a bummer. :( [file:nnn]

My original code will not produce this output because it cannot handle multiple stream insertions with just a single appended token for the location. The output instead becomes a big mess:

File not found! ' [main.cpp:61]foo.txt [main.cpp:61]' What a bummer. :( [main.cpp:61 ]

This can be accomodated by having errstream dump its contents to cout when the destructor is called, rather than when the stream insertion operator is called. The stream insertion operator, in turn, somply collects the tokens that will be dumped to cout before the location string. New code:

#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. :(";

}

The output is now:

Oh no. That was a bad thing. [main.cpp:38]

File not found! 'foo.txt' What a bummer. :( [main.cpp:41]

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜