Printf Debugging Revisited 59
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!"
Happy debugging!"
Re:aah, academic stuff (Score:2, Interesting)
Re:aah, academic stuff (Score:1)
My co-worker (also called Sasha, incidentally) holds the same belief, but it seems the main reason for this is that he doesn't know how to use a real debugger
Re:aah, academic stuff (Score:2)
Crash dumps only go so far. They're good for picking apart a program that crashed, but many errors are logic errors: being asked to add X+l (lower case L) and having the coder write X+1 (digit one) won't crash a program, b
Looks primitive. (Score:2, Insightful)
First look at the code... looks rather primitive[0]. Guess I have to read the paper to figure out what's new here?
Don't think I will.
[0] Which isn't necessarily a bad thing, but you'd wonder why it's here to begin with.
Re:Looks primitive. (Score:1)
But oh well, why did I expect a Slashdot reader to RTFA.
Re:Looks primitive. (Score:3, Insightful)
Second, he's right - your code is rather primitive, as you admit. Why not start with a much more advanced logging utility, and then speak about using the logging consistently?
Third, if your whole point was about a methodology, then talk about the methodology. Reading your article, it doesn't read like that - it reads much more like a User's Manual for how to use your code.
Fourth, what makes you t
Re:Looks primitive. (Score:2, Interesting)
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
Re:Looks primitive. (Score:2)
Second: I would actually argue that your code is far more complicated than it needs to be, for the intended use.
Third: Apparently there is no third. =)
Fourth: Sure, I could change your code to make it go away, but I think it would be much better if your code had its own mechanism for going away. I would tend to agree that anything inside "if (false)" should mostly compile away - so that's fair. I'd like to see a "#ifdef DEBUG" or somesuch in your code for that case.
Fifth: It's
Re:Looks primitive. (Score:1)
Fourth: Well, I could add some "#ifdef LOG_DISABLE". On the second thought, I'll do exactly that.
Your new point: you are close. Yes, it would be prohibitive, both space-wise and performance-wise, to print everything (in the case I describe, it can easily be 100K per cycle at maximal output).
But the p
WTF's up with the links? (Score:1, Insightful)
What's wrong with a simple link to the article? It already contains download links and links to the authors' websites. Splitting words up into multiple links isn't just annoying, but confuses people who use screen readers and Google. Editors, it's your job to massage submissions into a decent format.
Re:WTF's up with the links? (Score:1)
Some comments (Score:5, Insightful)
The first thing that jumps out at me is the coding style. Very junior programmer-ish. College student maybe? The style has that "everything crammed together" very diffcult to read feel. When I dug deeper I found the system to be over-designed and not well implemented.
Nice try though, get some experience then try again.
I've found that a simple C based logging facility is much more versatile. It can be used from C or C++ plus most programming languages and applications support calling external C libraries also.
Re:Some comments (Score:2)
The first thing that jumps out at me about your post is that you make snap judgements about people's experience and background based on how much whitespace they use. Very junior programmer-ish of you. Are you a college student, maybe?
Re:Some comments (Score:4, Insightful)
Re:Some comments (Score:1)
Re:Some comments (Score:4, Funny)
Re:Some comments (Score:2)
But it is a good standard? In particular, in order of importance, is the A) the standard everyone else on the project uses, and B) a common standard used by other successfull projects?
I have my own personal preferred coding standard. It is fairly close to B, but it fails in A at work. I get into a lot of trouble over this, and I'm wrong. Even though if I showed both (the company and my) standards to the world most programmers are likely to prefer mine (just a guess, but based on various style guides)
Re:Some comments (Score:3, Interesting)
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.
Re:Some comments (Score:1)
(Theres like a thousand versions of that out there.)
Re:Some comments (Score:2)
The most experienced (in terms of years of experience: more than 20 to be precise) (ex-)coder on my current project prefers an absolutely horrible coding style if you let him do as he pleases. Utterly unreadable for anyone but him (endless lines that wrap on even the widest of screens; NO blank lines; the weirdest indentation convention I ever saw; countless "this was/is experimental or old code" sections that have been commented
Re:Some comments (Score:1)
Re:Some comments (Score:1)
Re:Some comments (Score:1)
Re:Some comments (Score:3, Interesting)
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 reusa
Re:Some comments (Score:1, Interesting)
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
Re:Some comments (Score:2)
as in !LoggerConfig::is_nocolor()... it's much clearer to have it LoggerConfig::isColor().
Another thing:
won't it work just to do
os "\x1b[0;37;40m";
instead of those 2 lines?
I might be wrong here, if someone can correct me.
Re:Some comments (Score:2)
Now, why he didn't simply use the << operator on the literal string allowing the functionality of strlen() to be encapsulated by the routine that actually cares about the string's length is beyond me... :-) Oh, I bet that's exactly what you were trying to say but you didn't encode the < charact
Re:Some comments (Score:2, Interesting)
It's about leaving the logging code inside and improving it, rather than throwing it out shortly after it's used.
Re:Some comments (Score:1)
Indeed. Without wishing to be derogatory, another thing that sucks of junior programmer is that the author considers this insignificant hack important enough to be worthy of being on slashdot. The delusions of grandeur go with the territory.
Yes, it's mildly interesting but the fact that it badly reinvents a wheel already invented many times over makes it less so.
log4c++ (Score:3, Insightful)
How about Log4C++ [fsf.org], a port of the canonical Log4J logging package for Java.
Re:log4c++ (Score:2)
No big deal, I write a new logger for every project I write, it's a simple 5 minute hack.
Re:log4c++ (Score:5, Interesting)
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.
C++ makes it hard (Score:5, Interesting)
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: It's done like that (and it's actually readable when indented properly): 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.
Re:C++ makes it hard (Score:2)
You might want to bind *print-length* and *print-level* fairly low when you're printing repr; that may eliminate some of the [...]s. For that matter, you may want to wrap that whole thing in a with-standard-io-syntax, in case some print variables happen to have funky values when it's called.
Me, I tend to use (print `(foo before processing -> ,foo)) instead, but everybody's got their own style.
Instead of adverts for 2nd-year student projects (Score:5, Informative)
why not a link to a more professional and better-designed debugging library [sourceforge.net] instead? The author has made insane efforts to handle all kinds of error conditions which it looks like these kids haven't even thought of.
Wheel invented. News at 11. (Score:1)
19 comments in 4 hours? (Score:1, Offtopic)
Re:19 comments in 4 hours? (Score:2)
Re:19 comments in 4 hours? (Score:2)
If you'd actually read the comments, even if you hadn't looked at the code, you'd have some idea just how "hardcore" this is.
Re:19 comments in 4 hours? (Score:2)
Don't reinvent the wheel (Score:4, Informative)
Don't take the criticism too hard guys... (Score:3, Interesting)
Why is this on Slashdot at all? (Score:5, Informative)
#define LOG(logger) if ((logger).is_active()) (logger).os()
This will break if one writes:
if (value == 0)
LOG(xxx) "hello" endl;
else
The "else" gets interpreted as being attached to the "if" inside the LOG macro when it shouldn't.
It should be written as:
#define LOG(logger) if (!(logger).is_active()) ; else (logger).os()
For a much more expansive trace/log system see OSE at:
http://ose.sourceforge.net
and specifically
http://ose.sourceforge.net/browse.php?group=libra
and
http://ose.sourceforge.net/browse.php?group=libra
The OSE library has had this stuff for over ten years now.
My own thoughts (Score:1, Informative)
You can find it here along with an article I wrote what I though logging should support:
http://www.bluefish.se/aquarium/lime.html
PURE EVIL (Score:5, Informative)
Logger(const Logger& enable2 = *(Logger*)0);
(Trimmed to trick the lameness filter.)
Pure. Evil.
And don't go telling me "that's perfectly valid," cause you know what? I don't care if the C++ compiler accepts it, and I don't care if you do it in your code. That is just pure evil.
Meta-programming. (Score:2)
Re:Meta-programming. (Score:2)
I'm not a Java guy, so maybe I'm not catching all the nuances of the try/finally construct. It just looks like it could cause unwanted behavior.