Better way to do debug-logging? - c++

Is there a better, maybe more industry standard way to turn on and off debug logging throughout your code?
What I have currently is something similar to this:
#define logging
[.. in several places throughout the code ..]
#ifdef logging
cout << "My debug messages\n";
#endif
I just comment out the #define logging when it's no longer needed.
A couple of shortcomings with this approach seem to be:
I have to #define logging in every file I want to use it in
It's not very robust; I would prefer something like #define logging 1, and be able to check which logging-level is enabled to determine the granularity of my debug output. Unfortunately, to my knowledge, #ifdef doesn't care what value you choose, it just cares that it's defined
Are there any suggestions on how to better implement this?

It's not very robust; I would prefer something like #define logging 1, and be able to check which logging-level is enabled to determine the granularity of my debug output.
Well why don't you do that? Just don't test with #ifdef, but with #if:
#if logging>1
// something
#endif
Also - you could define logging in a separate file (like myDefines.h) and include it in your other files.
//myDefines.h
#define logging 2
//someOtherFile.h
#include "myDefines.h"
#if logging>1
// something
#endif

One suggestion:
You can #define logging in your project settings instead of in every file that you want to use it in.

You may want to checkout Google's glog project: https://code.google.com/p/google-glog/
But this might be more overhead than your're looking for.
Something simple you can try, granted your
compiler supports the -Dmacroname flag, you can turn
on logging with during compile time. For example:
g++ -Dlogging program.cpp -o program
will define the logging macro to 1.

Related

Where can I see ATLTRACE output?

I'm maintaining a C++ COM project. There are some trace lines like ATLTRACE(message);
I searched ATLTRACE. MSDN told Visual C++ output window will display it. However, the product is a release one. The customer won't have the source nor to debug it in VS. So is there any other convenient way to see it? Will Windows Event viewer catch that? Or I have to change the code? Win7, VS2013
The ATLTRACE only uses only the debug output and it works only in the Debug version!
So you may give the enduser a debug version for testing purpose, and use DebugView from Sysinternals. But this may be complicated because you also have to over the debug runtimes that are not redistributable.
But you can easily write your own MY_TRACE macro that has the same functionality.
#define MY_TRACE GetMyTracer() // returns object of CMyTracer
...
class CMyTracer
{
...
// Helper operator to get the trace commands. They call the TraceV functions
void operator()(PCSTR pszFormat, ...);
void operator()(PCWSTR pszFormat, ...);
// Worker functions that do the real job calling TraceV functions
void Trace(PCSTR pszFormat, ...);
void Trace(PCWSTR pszFormat, ...);
// Allowed to be virtual to do some internal mystique stuff, like redirecting and this functions perform all output...
virtual void TraceV(PCSTR pszFormat, va_list args);
virtual void TraceV(PCWSTR pszFormat, va_list args);
...
Now you can use this instead of ATLTRACE
...
MYTRACE("Simple output\n");
MYTRACE("More complex output %d\n", 4711);
Note: It is not wise to replace all ATLTRACE macros with your own replacement. You may spread your trace output onto locations were it don't have impact un speed, but is worth the information.
ATLTRACE is a macro that compiles to nothing in a release build. You'll need to rebuild the project with the _DEBUG macro defined (see <atltrace.h>) to get those to display. However, output generated by ATLTRACE is a debug output string, and will typically only display in the debugger's output window.
If there is important information you need, and if it is in code you control, you'll be better off changing the ATLTRACE macro usage to something else, to either log to the event log or a log file the customer can send to you.
As mentioned by 1201ProgramAlarm, release builds of ATL projects have ATLTRACE macros evaluated to nothing and the binary has no real code generated for respective source code lines. That is, you cannot see the output without altering source code.
In order to not alter the project much, you can redefine the tracing macro itself and produce release build with tracing capabilities where output is routed as defined by you, for example to standard debug output using OutputDebugString API.
See:
How to enable the TRACE macro in Release mode?
AtlReleaseTrace

Fastest way to make console output "verbose" or not

I am making a small system and I want to be able to toggle "verbose" text output in the whole system.
I have made a file called globals.h:
namespace REBr{
extern bool console_verbose = false;
}
If this is true I want all my classes to print a message to the console when they are constructing, destructing, copying or doing pretty much anything.
For example:
window(string title="",int width=1280,int height=720):
Width(width),Height(height),title(title)
{
if(console_verbose){
std::cout<<"Generating window #"<<this->instanceCounter;
std::cout<<"-";
}
this->window=SDL_CreateWindow(title.c_str(),0,0,width,height,SDL_WINDOW_OPENGL);
if(console_verbose)
std::cout<<"-";
if(this->window)
{
this->glcontext = SDL_GL_CreateContext(window);
if(console_verbose)
std::cout<<".";
if(this->glcontext==NULL)
{
std::cout<<"FATAL ERROR IN REBr::WINDOW::CONSTR_OPENGLCONTEXT: "<<SDL_GetError()<<std::endl;
}
}
else std::cout<<"FATAL ERROR IN REBr::WINDOW::CONSTR_WINDOW: "<<SDL_GetError()<<std::endl;
if(console_verbose)
std::cout<<">done!"<<endl;
}
Now as you can see I have a lot of ifs in that constructor. And I REALLY dont want that since that will slow down my application. I need this to be as fast as possible without removing the "loading bar" (this helps me determine at which function the program stopped functioning).
What is the best/fastest way to accomplish this?
Everying in my system is under the namespace REBr
Some variants to achieve that:
Use some logger library. It is the best option as it gives you maximum flexibility and some useful experience ;) And you haven't to devise something. For example, look at Google GLOG.
Define some macro, allowing you to turn on/off all these logs by changing only the macro. But it isn't so easy to write such marco correctly.
Mark your conditional flag as constexpr. That way you may switch the flag and, depending on its value, compiler will optimise ifs in compiled program. But ifs will still be in code, so it looks kinda bulky.
Anyway, all these options require program recompilation. W/o recompilation it is impossible to achieve the maximum speed.
I often use a Logger class that supports debug levels. A call might look like:
logger->Log(debugLevel, "%s %s %d %d", timestamp, msg, value1, value2);
The Logger class supports multiple debug levels so that I can fine tune the debug output. This can be set at any time through the command line or with a debugger. The Log statement uses a variable length argument list much like printf.
Google's logging module is widely used in the industry and supports logging levels that you can set from the command line. For example (taken from their documentation)
VLOG(1) << "I'm printed when you run the program with --v=1 or higher";
VLOG(2) << "I'm printed when you run the program with --v=2 or higher";
You can find the code here https://github.com/google/glog and the documentation in the doc/ folder.

'Assert Failed' message incomplete using CppUnit and TFS2015

Using: MSTest / CppUnit / TFS2015 / VS2013 / C++
I'm debugging a test that runs fine locally and fails on the build machine (which I don't have access to). This morning I sat down and was presented with almost all of my tests passing -- except one. The test happens to be comparing two rather large strings and the (usually) very helpful Assert failed. Expected:<... never made it to the Actual:<... part because the string was too long. It's just a simple: Assert::AreEqual(expectedStr, actualStr);.
Right now my workaround is to write a file to a network path that I have access to from within the test (which is already an integration type test luckily -- but still...). Oh -- and did I mention that I have to run a build that will take 40 minutes even if I set Clean Workspace to None in my build process parameters to even get the test to run? That's a whole other question for another post =/.
Is there a way to look at the full results of a test assertion failure (without, for example, a string comparison being cut off)? A test run log file maybe?
According to your description, you want to express assertion failure messages in C++. Check this case may help you:
"
A common solution for this problem is to create an assert macro. For an example see this question. The final form of their macro in that answer was the following:
#define dbgassert(EX,...) \
(void)((EX) || (realdbgassert (#EX, __FILE__, __LINE__, ## __VA_ARGS__),0))
In your case, the realdbgassert would be a function that prints any relevant information to stderr or other output console, and then calls the assert function itself. Depending on how much information you want, you could also do a stack dump, or log any other relevant information that will help you identify the issue. However, it can be as simple as passing a printf-esque format string, and relevant parameter value(s).
Note that if you compiler doesn't support variadic macros, you can create macros that take a specific number of parameters instead. This is slightly more cumbersome, but an option if your compiler lacks the support, eg:
#define dbgassert0(EX) \ ...
#define dbgassert1(EX,p0) \ ...
#define dbgassert2(EX,p0,p1) \ ...
"

Printing output on the Output Window in Visual C++ IDE

How do I print on the output window in Visual C++? The project that I am working on isn't of a console window project type. That's when I build and run it, it doesn't open a console window. Instead, it opens a win32 application, which isn't built by me. I am just adding things to it.
I am pretty new to C++ and because I couldn't print variables out on any console, it makes it very hard for me to debug.
Since the Visual Studio 2010 project doesn't launch console when I build and run it, can I still print outputs such as variables and others on the Output window of the IDE?
Thanks for any help.
You can use OutputDebugString("..."); to print to the Output window of Visual Studio. You have to #include <windows.h> though.
I have written a portable TRACE macro.
On MS-Windows, it is based on OutputDebugString as indicated by other answers.
Here I share my work:
#ifdef ENABLE_TRACE
# ifdef _MSC_VER
# include <windows.h>
# include <sstream>
# define TRACE(x) \
do { std::stringstream s; s << (x); \
OutputDebugString(s.str().c_str()); \
} while(0)
# else
# include <iostream>
# define TRACE(x) std::clog << (x)
# endif // or std::cerr << (x) << std::flush
#else
# define TRACE(x)
#endif
example:
#define ENABLE_TRACE //can depend on _DEBUG or NDEBUG macros
#include "my_above_trace_header.h"
int main (void)
{
int v1 = 123;
double v2 = 456.789;
TRACE ("main() v1="<< v1 <<" v2="<< v2 <<'\n');
}
Please feel free to give any improvements/suggestions/contributions ;-)
Instead of printing to the Output window in VS as indicated by other answers, I prefer to create a console window in my GUI apps, then use regular printf or cout to write debugging info to it. This has the benefit that you can do it even when you run without the debugger.
See this site for a simple function that sets up a console.
I have used this in the past, although not with a win32 application. You could give it a shot though :)
http://www.cplusplus.com/forum/lounge/17371/
You can use the Windows function OutputDebugString (see here) to send output to debuggers. These outputs are shown in the VS output window. You can also watch these outputs with external applications, e.g. DebugView.
Remember to remove these statements from your production code if you don't want other people to see these debug messages (which would otherwise be possible using tools like DebugView...)

Is there a TRACE statement for basic win32 C++?

In MFC C++ (Visual Studio 6) I am used to using the TRACE macro for debugging. Is there an equivalent statement for plain win32?
_RPTn works great, though not quite as convenient. Here is some code that recreates the MFC TRACE statement as a function allowing variable number of arguments. Also adds TraceEx macro which prepends source file and line number so you can click back to the location of the statement.
Update: The original code on CodeGuru wouldn't compile for me in Release mode so I changed the way that TRACE statements are removed for Release mode. Here is my full source that I put into Trace.h. Thanks to Thomas Rizos for the original:
// TRACE macro for win32
#ifndef __TRACE_H__850CE873
#define __TRACE_H__850CE873
#include <crtdbg.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#ifdef _DEBUG
#define TRACEMAXSTRING 1024
char szBuffer[TRACEMAXSTRING];
inline void TRACE(const char* format,...)
{
va_list args;
va_start(args,format);
int nBuf;
nBuf = _vsnprintf(szBuffer,
TRACEMAXSTRING,
format,
args);
va_end(args);
_RPT0(_CRT_WARN,szBuffer);
}
#define TRACEF _snprintf(szBuffer,TRACEMAXSTRING,"%s(%d): ", \
&strrchr(__FILE__,'\\')[1],__LINE__); \
_RPT0(_CRT_WARN,szBuffer); \
TRACE
#else
// Remove for release mode
#define TRACE ((void)0)
#define TRACEF ((void)0)
#endif
#endif // __TRACE_H__850CE873
From the msdn docs, Macros for Reporting:
You can use the _RPTn, and _RPTFn macros, defined in CRTDBG.H, to replace the use of printf statements for debugging. These macros automatically disappear in your release build when _DEBUG is not defined, so there is no need to enclose them in #ifdefs.
There is also OutputDebugString. However that will not be removed when compiling release.
Trace macros that provide messages with source code link, run-time callstack information, and function prototype information with parameter values:
Extended Trace: Trace macros for Win32
I just use something like this (from memory, not tested at all...)
#define TRACE(msg) {\
std::ostringstream ss; \
ss << msg << "\n"; \
OutputDebugString(msg.str()); \
}
And then I can write things like :-
TRACE("MyClass::MyFunction returned " << value << " with data=" << some.data);
You can wrap that in some #ifdefs to remove it in release builds easily enough.
I found that using the _RPT() macro will also work with a C source file in Visual Studio 2005. This article Debugging with Visual Studio 2005/2008: Logging and Tracing provides an overview of TRACE, _RPT, and other logging type macros.
I generate a line for a log file called the ASSRTLOG which contains logs and when writing the log to the file, I also do the following source code line:
_RPT1(_CRT_WARN, "ASSRTLOG: %s", szLog1);
This line puts the same log that is going into the log file into the output window of the Visual Studio 2005 IDE.
You might be interested in the mechanics behind the approach we are using for logging. We have a function PifLogAbort() which accepts a series of arguments that are then used to generate a log. These arguments include the name of the file where the log is being generated along with the line number. The macro looks like this:
#define NHPOS_ASSERT_TEXT(x, txt) if (!(x)) { PifLogAbort( (UCHAR *) #x , (UCHAR *) __FILE__ , (UCHAR *) txt , __LINE__ );}
and the function prototype for PifLogAbort() look like this:
PifLogNoAbort(UCHAR *lpCondition, UCHAR *lpFilename, UCHAR *lpFunctionname, ULONG ulLineNo)
and to use the macro we will insert a line like this:
NHPOS_ASSERT_TEXT(sBRetCode >= 0, "CliEtkTimeIn(): EtkTimeIn() returned error");
What this macro will do is that if the return code is less than 0 (the assertion fails), a log will be generated with the provided text. The log includes the condition that generated the log along with file name and line number.
The function PifLogAbort() generates logs with a specified length and treats the output file as a circular buffer. The logs have a time and date stamp as well.
In those cases where we want to generate the descriptive text dynamically at run time, perhaps to provide the actual error code value, we use the sprintf() function with a buffer as in the following code sequence:
if (sErrorSave != STUB_BM_DOWN) {
char xBuff[128];
sprintf(xBuff, "CstSendBMasterFH: CstComReadStatus() - 0x%x, sError = %d", usCstComReadStatus, CliMsg.sError);
NHPOS_ASSERT_TEXT((sErrorSave == STUB_BM_DOWN), xBuff);
}
If we want the logs to not be generated, all we need to do is to go to the single header file where the macro is defined and define it to be nothing then recompile. However we have found that these logs can be very valuable when investigating field issues and are especially useful during integration testing.
Windows Events are a potential replacement for TRACE macros, depending on your particular scenario. The code gets compiled into both Debug and Release configurations. Event tracing can then be dynamically enabled and disabled, displayed in real-time, or dumped on a client's machine for later diagnosis. The traces can be correlated with trace information gathered from other parts of the OS as well.
If you merely need to dump information whenever code reaches certain checkpoints, together with variable content, stack traces, or caller names, Visual Studio's Tracepoints are a non-intrusive option to do so.