Inside the <vector> header, there is code like this:
_DEBUG_ERROR("vector iterator not dereferencable");
_SCL_SECURE_OUT_OF_RANGE;
Which halts the program with a message and gives the programmer a chance to debug the code.
For a little toy project, I want to use _DEBUG_ERROR myself. It is defined in <xutility>.
However, when I include <xutility> and try to use _DEBUG_ERROR, I get the following error:
error C3861: "_Debug_message": identifier not found.
But _Debug_message is defined inside <xutility>, in line 28! Why does the compiler complain?
Also, is there another (maybe even somewhat portable?) way to halt the program for debugging?
Not 100% certain but I'm fairly sure it's actually std::_Debug_message. And PlasmaHH is right: assert() is the normal solution. You can write assert(!"message") to get a custom message. (Note the !)
You can use ASSERT or _ASSERT macro for assert-and-debug. Or, you can craft your own assert-macro. Use the definition of _ASSERT (taken from crtdbg.h):
#define _ASSERT_EXPR(expr, msg) \
(void) ((!!(expr)) || \
(1 != _CrtDbgReportW(_CRT_ASSERT, _CRT_WIDE(__FILE__), __LINE__, NULL, L"%s", msg)) || \
(_CrtDbgBreak(), 0))
The important function here is _CrtDbgReportW, which will display the assertion dialog-box having three standard buttons (Abort, Retry and Ignore). Depending on return value you can then call other functions. In the macro given above, function _CrtDbgBreak is called when user hits 'Retry' button (which causes function to return 1, see MSDN).
You may write to a log file, display to debug output window (using OutputDebugString), or do things you may like.
Related
I'm having trouble with writing an assignment for uni in an old Borland c++ standard.So I have this macro which HAS to be used like this: PREPAREENTRY(9,0); where the first argument will always range from 0 to 255 and second will always be 0 or 1. Without going into much detail unless necessary it's supposed to automatically generate a unique interrupt function for every entry in the interrupt vector table.
My code is as follows:
#define PREPAREENTRY(ivtNo, oldInterrupt) \
extern IVTEntry ivtEntry##ivtNo; \
void interrupt interrupt##ivtNo(...){ \
ivtEntry##ivtNo.signal(); \
if(oldInterrupt) \
ivtEntry##ivtNo.oldInterrupt(); \
} \
IVTEntry ivtEntry##ivtNo(ivtNo, interrupt##ivtNo);
(I've tried not putting ; on the last line of macro definition, but it still gives me the same error)
When I don't use the macro and switch every ivtNo with 9 and oldInterrupt with 0, the code works. But when I use the macro the code can't compile and it gives me this error Error ..\src\keyevent.cpp 17: Statement missing ; in function interrupt interrupt9(...). I've tried moving around a bunch of stuff and writing it several times but it's always either that error or missing ) error.
I will provide you with more details if needed, but if anyone has any clue what could be causing these errors I'd be very grateful!
SOLVED
Macro argument and function inside of IVTEntry class that I'm using inside of the macro had the same name. So the macro called ivtEntry9.0(); instead of ivtEntry9.oldInterrupt();
I'm using Qt5.9, a simple check:
assert(pobjNode != NULL);
Will cause the Qt Signal Received error dialog to be displayed which doesn't give any helpful information about where the problem is or what it is.
Is there a way to replace this useless information with something a bit more helpful?
What I'm thinking of is a way to set-up the dialog to display what could be an error in the event of an error.
Q_ASSERT is a custom assert macro which supposedly enhances the standard assert function.
The error message is handled by qFatal(), which can behave slightly better on some platforms than the standard assert macro. For example on Windows it will trigger the Visual Studio debugger at the point where the assertion fails instead of just calling abort().
You can also redirect the output of Qt error message functions such as qFatalto your custom message handler ( with qInstallMessageHandler() ). It can be useful for example if you want to redirect the errors message to a file.
Also note that Q_ASSERT is disabled with the macro QT_NO_DEBUG(while assert is disabled by NDEBUG) : this can be used to separate your asserts between Qt-related code and the rest.
Q_ASSERT_X Prints the message what together with the location where, the source file name and line number if test is false.
Prints the message what together with the location where, the source file name and line number if test is false.
Example:
// File: div.cpp
#include <QtGlobal>
int divide(int a, int b)
{
Q_ASSERT_X(b != 0, "divide", "division by zero");
return a / b;
}
to read more on test and debug.
You might define your own MY_ASSERT macro. On Linux it could even call another function which uses Glibc backtrace functions or Ian Taylor's libbacktrace library (provided your code is compiled with DWARF debug information using g++ -g) and perhaps display such information in a modal dialog, or on stderr. However, it should probably not return. Read also about Qt and Unix signals and signal-safety(7).
But assert detects a bug which you should correct. Try hard to avoid shipping code with such programmer bugs.
On Linux, the usual assert -it is a macro defined in /usr/include/assert.h- will call on failure __assert_fail (in your C library, but you might redefine it yourself) which would indirectly call abort which indirectly makes a core dump which you can inspect post-mortem using the gdb debugger. You only need to enable core dumps (using ulimit -c builtin in your bash terminal).
As part of a bigger project ( the ff activex plugin for Mozilla Firefox) there is this code snippet:
if (CombineRgn(hrgnClip, hrgnClip, hRGN, RGN_AND) != ERROR)
{
::InvalidateRgn(m_hWndParent, hrgnClip, fErase);
}
When I build in VS2012 I get "Error C2065: 'ERROR' : undeclared identifier"
ERROR is defined in wingdi.h like this:
...
/* Region Flags */
#define ERROR 0 // it wont build when this macro is used
#define NULLREGION 1 // it builds when this macro is used
#define SIMPLEREGION 2
#define COMPLEXREGION 3
#define RGN_ERROR ERROR
...
The strange thing is that if I replace ERROR (just to see if it builds OK) with NULLREGION or SIMPLEREGION (which are macros in the same file, just two lines below the offending one) in the if statement above, the code builds OK. When I use ERROR, the code wont build.
Is it possible that the ERROR macro defined above gets masked by some keyword or another macro or some such by Visual Studio?
The problem here is that ERROR actually appears in the compile error message. That should not happen, the preprocessor should have substituted it with 0.
So somewhere in a .h file you #included after windows.h, some programmer took the 10 second shortcut to a macro name collision problem and wrote this:
#undef ERROR
You'd need to find that line and remove it. That's likely to be difficult and liable to give you a maintenance headache since that's a file you don't own and might well be updated in the future, forcing you to make that change over and over again. The alternative is to redefine it yourself:
#define MYGDIERROR 0
...
if (CombineRgn(hrgnClip, hrgnClip, hRGN, RGN_AND) != MYGDIERROR)
//etc...
Which still gives you a maintenance problem and requires you taking a bet that the return value definition of CombineRgn() is never going to change. That's a very safe bet, GDI is cast in stone.
I am working with HANDLES, the first one, nextColorFrameEvent is an event handler and the second one is a stream handler. They are being initialized in the following piece of code:
nextColorFrameEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
hr = nui->NuiImageStreamOpen(
NUI_IMAGE_TYPE_COLOR,
NUI_IMAGE_RESOLUTION_640x480,
0,
2,
nextColorFrameEvent,
&videoStreamHandle);
I want to properly deal with them on destruction, while not creating errors at the same time. Sometimes the initializer wont be called, so both HANDLEs are still NULL when the software comes to an end. Thats why I want to check first if the HANDLEs are properly initialized etc. and if they are, I want to close them. I got my hands on the following piece of code for this:
if (nextColorFrameEvent && nextColorFrameEvent != INVALID_HANDLE_VALUE)CloseHandle(nextColorFrameEvent);
#ifdef QT_DEBUG
DWORD error = GetLastError();
qDebug()<< error;
#endif
if (videoStreamHandle && videoStreamHandle != INVALID_HANDLE_VALUE)CloseHandle(videoStreamHandle);
#ifdef QT_DEBUG
error = GetLastError();
qDebug()<< error;
#endif
But this is apperently incorrect: if I do not run the initializer and then close the software this piece of code runs and gives me a 6:
Starting C:\...\Qt\build-simpleKinectController-Desktop_Qt_5_0_2_MSVC2012_64bit-Debug\debug\simpleKinectController...
6
6
C:\...\Qt\build-simpleKinectController-Desktop_Qt_5_0_2_MSVC2012_64bit-Debug\debug\simpleKinectController exited with code 0
which means:
ERROR_INVALID_HANDLE 6 (0x6) The handle is invalid.
Which means that closeHandle ran anyway despite the tests. What tests should I do to prevent closing when the handle is not a valid HANDLE?
Bonus question: if I run the initializer this error will no longer appear when only closing colorFrameEvent, but will still appear when closing videoStreamHandle:
Starting C:\...\Qt\build-simpleKinectController-Desktop_Qt_5_0_2_MSVC2012_64bit-Debug\debug\simpleKinectController...
0
6
C:\...\Qt\build-simpleKinectController-Desktop_Qt_5_0_2_MSVC2012_64bit-Debug\debug\simpleKinectController exited with code 0
Do I need a diffent function to close a stream handler?
nui->NuiImageStreamOpen(...) does not create a valid Windows handle for the stream but instead it creates an internal handle inside the driver side.
So you can not use windows API to release/close stream handle !!!
To do that just call nui->NuiShutdown(). I have not yet used the callback event but I think its a valid windows handle and should be closed normally.
if you need just to change settings you can always call nui->NuiImageStreamOpen(...) with new settings. No need to shutdown ...
I would also welcome function nui->NuiImageStreamClose(...); because current state of API complicates things for long term running aps with changing sensor configurations.
CreateEvent (http://msdn.microsoft.com/en-us/library/windows/desktop/ms682396(v=vs.85).aspx) returns NULL if an event was not created.
You are checking against INVALID_HANDLE_VALID which is not NULL.
You are probably trying to double-close a handle. That is likely to generate ERROR_INVALID_HANDLE 6. You can't detect this with your test, because the first CloseHandle(nextColorFrameEvent); did not change nextColorFrameEvent.
The solution is to use C++ techniques, in particular RAII. There are plenty of examples around how to use shared_ptr with HANDLE. shared_ptr is the standard solution to run cleanup code at most once, after everyone is done, and only if anybody actually allocated a resource.
there is a good way of debugging that I'm particularly fond of, despite being all writen in macros, which are nasty, but in this case they work wonders.
Zed's Awesome Debug Macros
there are a couple of things I like to change though. They make extensive use of goto, which I tend to avoid, specially in c++ projects, because otherwise you wouldn't be able to declare variables mid-code. This is why I use exit(-1) instead, or, in some projects, I mod the code to try, throw, catch c++. Since you are working with Handles, a good thing would be setting a variable and telling the program to close itself.
here is what I mean. Take this piece of code from the macros (i assume you would read the exercise and familiarize with the macros):
#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
i'd change
goto error;
to something like
error = true;
the syntax inside the program would be something like, and I took it from a multithread program I'm writing myself:
pRSemaphore = CreateSemaphore(NULL, 0, MAX_TAM_ARQ, (LPCWSTR) "p_read_semaphore");
check(pRSemaphore, "Impossible to create semaphore: %d\n", GetLastError());
As you can see, GetLastError is only called when pRSemaphore is set to null. There are somewhat fancy mechanisms behind the macro (at least they are fancy for me), but they are hidden inside the "check" mask, so you needn't worry about them.
next step is to treat the error with something like:
inline void ExitWithError(bool &err) {
//close all handles
//tell other related process to do the same if necessary
exit(-1);
}
or you could just call it inside the macro like
#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; ExitWithError(); }
hope I could be of any help
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.