Slashdot Mirror


Printf Debugging Revisited

gsasha writes "After long nights spent in debugging, w e have developed a C++ logging facility geared for debugging - and an article that describes our debugging methodology. The article consists of two parts: the first one describes the basics of the method, and the second one presents advanced techniques (to be completed if there is enough reader interest).
Happy debugging!"

9 of 59 comments (clear)

  1. C++ makes it hard by YGingras · · Score: 5, Interesting
    It's hard to do a good printing debugger in C++. The lack of introspection throws most of the work in the hands of the pre-processor/developper.

    When I learned Common Lisp, the first macro I did was for printing debugging. It reads the expresions it is debugging, prints it (and shortens it with "..." if needed), evaluates it, prints the results and returns the results.

    What a monster you might say. Lets fist see an example of it's use:
    CL-USER> (+ 16 34 (- 6 7 8) (/ (* 3 (expt 4 1/2)) 2 3))
    42.0
    CL-USER> (dbg (+ 16 34 (dbg (- 6 7 8)) (dbg (/ (* 3 (dbg (expt 4 (/ 1 2)))) 2 3))))
    (- 6 7 8): -9
    (EXPT 4 (/ 1 2)): 2.0
    (/ (* 3 (DBG (EXPT 4 (/ 1 2)))) 2 3): 1.0
    (+ 16 34 (DBG (- 6 7 [...] 4 (/ 1 2)))) 2 3))): 42.0
    42.0
    It's done like that (and it's actually readable when indented properly):
    (defmacro dbg (expr)
    `(let ((val ,expr)
    (repr (format nil "~A" ',expr)))
    (if (> (length repr) 50)
    (format t "~A [...] ~A: ~A~%"
    (subseq repr 0 20)
    (subseq repr (- (length repr) 20))
    val)
    (format t "~A: ~A~%" repr val))
    val))
    Most of the hard work is taken away by the ability of the program to read itself, by dynamic typing and by the notion that there are no statements, only expressions. That being said, I don't claim that you should never use C++, just that it lacks introspection and that it makes printing debuging a lot harder.
  2. Re:Some comments by Soul-Burn666 · · Score: 2, Interesting

    If you look at the links, you can see they are both PhD students in the Technion institute of technology.
    It's actually pretty strange the coding style is like this, specifically the hard coded functions like get_enabled1 or set_red instead of variables and constants like get_enabled(unsigned num) and set_color(Logger::color col).
    I'm particularly surprised because I study in the same institute and faculty as they do and the programming courses we have are pretty demanding and specifically point to code reusability instead of code copying.

    --
    ^_^
  3. Re:log4c++ by Mysteray · · Score: 4, Interesting
    we have developed a C++ logging facility geared for debugging

    My first reaction to this was, who hasn't?

    I agree with some of the other posters that their code has some, well, "interesting" features. I have to say it never would have occurred to me to use strcmp on a compile-time constant in a member initialization.

    That they use, but don't derive from, std::ostream for this is another example. It's not exactly trivial to do so, but it's also hard to argue against not doing it for something like this without good reason. But since there's not a single comment in the source files except some revision control macros we're just left to wonder.

  4. Re:Some comments by Anonymous Coward · · Score: 1, Interesting

    The manipulators are particularly awful. They're a bunch of little functions that are copy/pasted just to change a string literal. Some of them don't even change the literal!

    std::ostream& set_dark_white(std::ostream& os)
    {
    if (!LoggerConfig::is_nocolor()) {
    const char* buf = "\x1b[0;37;40m";
    os.write(buf, strlen(buf));
    }
    return os;
    }
    std::ostream& set_gray(std::ostream& os)
    {
    if (!LoggerConfig::is_nocolor()) {
    const char* buf = "\x1b[0;37;40m";
    os.write(buf, strlen(buf));
    }
    return os;
    }

    std::ostream& reset_color(std::ostream& os)
    {
    if (!LoggerConfig::is_nocolor()) {
    const char* buf = "\x1b[0;37;40m";
    os.write(buf, strlen(buf));
    }
    return os;
    }

  5. Don't take the criticism too hard guys... by museumpeace · · Score: 3, Interesting
    Virtually every project of 10 or more engineers that I have been on in my 30 years of software dev has cooked up its own logging facility. You are on the back of a very crowded bus here. Depending on whether memory, disk i/o resources or realtime and multithread requirements reign in your application, rather different logging approaches are applicable. Being able to dump the Nth occurance is a nice feature but so many more are needed. THE BIGGEST DIFFERENCE I SEE between your logger kit and some I have used/written is that you published the code. A partial feature checklist I would be looking for:
    • []has both compile time and run time mechanism to set severity thresholds.
    • [] idenifies the process/thread from which the logging call is issued
    • [] can generate some kind of event ID so context can be deduced even when the same message occurs many times.
    • []timestamping: this can give you a poor man's perfmon with added programability.
    • [] supports detection of recursion by indenting printouts that are called as you go deeper on the stack
    • [] NOMENCLATURE REGULARITY: a syntax for timestamps, severity, function name from which print is called, etc so that you can automate [eg with AWK etc ] the sorting and dredging for clues in a long output run.
    • []when not in use, can be "turned off" with no compile or run time overhead but still present as comments.
    ...there are more, believe me.
    --
    SLASHDOT: news for people who can't concentrate on work or have no life at all and got tired of yelling back at the TV.
  6. Re:Some comments by jeif1k · · Score: 2, Interesting

    While their styles will vary greatly, old timers will almost uniformly prefer an easy-for-others-to-read style.

    Easy-to-read for whom? Easy to read for an absolute beginner? Easy to read for an expert programmer?

    There is no style that works for every reader--a style that makes code easy to read for beginners can obscure patterns and shorthands that make code easy to read for expert programmers.

  7. Re:Some comments by gsasha · · Score: 2, Interesting

    Well, if you didn't RTFA, then you missed the point. The article is not about "oh, we wrote this wonderful logging mechanism". It's about the *methodology* of debugging almost exclusively by logging (as opposed to *sometimes* doing postmortem analysis by looking at the logs).
    It's about leaving the logging code inside and improving it, rather than throwing it out shortly after it's used.

  8. Re:aah, academic stuff by gsasha · · Score: 2, Interesting

    Actually, it's not academic stuff and never meant to be. It's a simple article describing a nice methodology... and actually, it's not that much about the logger implementation (it isn't at all), but about how using debugging by logging consistently is a powerful technique.

  9. Re:Looks primitive. by gsasha · · Score: 2, Interesting
    Ok then.

    First: my fault ;)

    Second: because you don't need a much more advanced logging facility for the intended use.

    Fourth: Whoa! That's easy: #define LOG(x) if (false) os. But actually, yes, I do ask people to not throw logging out once it's there. The reason it's not expensive when not used is that the branches in the "if(is_active())" do not change throughout the program, and thus are predicted very well and cost very little. I actually did measurements about the overhead of the mechanism and found it to be very small.

    Fifth: We have used this methodology in several very complex projects, and with very good results. You are free to use other debugging methods if you wish.

    And anyway, an article such as this is a fine way to research on how will people use my utility :)