Now I am working on this fair scheduling for my B Tech Project (BTP). Already having written a 1000 lines of code, it is a great pain to debug it. More so if you do not know which function might have caused the error. I needed a logger which could log all the events. The events include entering a function, any important calculation/decision it makes, any return values, so that if my program breaks down I can exactly pinpoint the source of error simply looking at the log file generated.
I have no idea if any inbuilt logging functionality exists for C programs or not. Either way, I did not have much time to google up and learn how to use it. I decided to make my own logger, a simple one, which would serve my purpose. It hardly took me 10 minutes to get over with it.
One of the important functionalities that I wanted my logger to have is indentation. The log should be properly indented, just the same way as we indent the code. When the program control enters a new function, the logging should get indented to right, and when it leaves the function, the logging should get indented by the same amount to the left. So I defined two macros, $$INDENT$$ and $$OUTDENT$$. To make them work, I defined a global variable – $$logIndent$$. The $$logIndent$$ would at any given time contain the amount of space by which the log has to be indented. Obviously, I initialized it with 0. Also defined is a global variable called $$indentVal$$ which is the amount of spaces with which the indentation should take place. I like the value to be 2. The two macros are
#define INDENT logIndent += indentVal #define OUTDENT logIndent -= indentVal int indentVal = 2; int logIndent = 0;
I defined another macro called $$SPACES$$ which would print the number of spaces to produce the required indentation.
int tempIndent; FILE *logFile; #define SPACES for(tempIndent = 0; tempIndent < logIndent; tempIndent++) fprintf(logFile, " ");
Obviously $$tempIndent$$ is a globally declared temporary variable and $$logFile$$ is the file pointer to the file where the log has to be written. I initialize the $$logFile$$ pointer in the $$main()$$ part of my program.
And finally coming to the logger, I created a custom $$printf()$$ statement using the $$vprintf()$$ command. I call my logger as $$LogThis()$$. Its declaration is as follows
void LogThis(const char *format, ...);
It is constructed as follows
void LogThis(const char *format, ...) {
va_list args;
va_start(args, format);
SPACES;
vfprintf(logFile, format, args);
va_end(args);
}
That’s it ! To use this logger, I have to do the following in my function :
#include <stdio .h>
#include <stdarg .h>
void TestLogger() {
int returnVal;
float retVal;
LogThis("<testlogger>\n");
INDENT;
/**
* Inside the function do whatever you want to
*/
LogThis("Returns: %d, %f\n", retrunVal, retVal)
OUTDENT;
LogThis("</testlogger>\n");
}
Done ! A well indented log will be produced. This has really helped me debug the code. I do not have to gdb from the last point that worked in my program. Instead, I know which function the program control was in when it threw an error. I need to gdb from that function onwards only, thus reducing the debuging time considerably. Also, in case of errors, I can increase the debugging data for that particular function, thus eliminating the need to use gdb at all.
Popularity: 9% [?]
Related posts:
Have you looked into log4cpp? It's quite powerful, though it takes a while to learn and is overkill.
Google's logging library, now opensource is the best I've seen. It's asynchronous and has multiple outputs. I can call a log function, and that won't stop the rest of my program from running. It also tells me which file and line number fired the log. I can put in a lot of DEBUG and INFO logs, with a few ERROR and WARN logs, and prune the previous two for final releases, so only important logs are shown, while you can enable the lower level logs for fine grained analysis if the program starts to break.
Have you looked into log4cpp? It’s quite powerful, though it takes a while to learn and is overkill.
Google’s logging library, now opensource is the best I’ve seen. It’s asynchronous and has multiple outputs. I can call a log function, and that won’t stop the rest of my program from running. It also tells me which file and line number fired the log. I can put in a lot of DEBUG and INFO logs, with a few ERROR and WARN logs, and prune the previous two for final releases, so only important logs are shown, while you can enable the lower level logs for fine grained analysis if the program starts to break.
Hey Andy, thanks a lot for the info. The glog is based only on C++ style streams. I am looking into the log4c now, and shall integrate it into my project.
I never knew about these. The only other logger I think I have used is that of Ruby on Rails, which prompted me to make one for myself in C.
Hey Andy, thanks a lot for the info. The glog is based only on C++ style streams. I am looking into the log4c now, and shall integrate it into my project.
I never knew about these. The only other logger I think I have used is that of Ruby on Rails, which prompted me to make one for myself in C.