Qt SIGABRT alternative message? - c++

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).

Related

How do I use _DEBUG_ERROR in my own code?

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.

how to get function name and line number when project crashed in release mode

i have a project in C++/MFC
when i run its in debug mode and project crashed
i can get function and line number of code
with SetUnhandledExceptionFilter function
but in release mode i can not get it
i am test this function and source
_set_invalid_parameter_handler msdn.microsoft.com/en-us/library/a9yf33zb(v=vs.80).aspx
StackWalker http://www.codeproject.com/KB/threads/StackWalker.aspx
MiniDumpReader & crashrpt http://code.google.com/p/crashrpt/
StackTracer www.codeproject.com/KB/exception/StackTracer.aspx
any way to get function and line of code when project crashed in release mode
without require pdb file or map file or source file ?
PDB files are meant to provide you this information; the flaw is that don't you want a PDB file. I can understand not wanting to release the PDB to end users, but in that case why would you want them to see stack trace information? To me your goal is conflicting with itself.
The best solution for gathering debug info from end users is via a minidump, not by piecing together a stack trace on the client.
So, you have a few options:
Work with minidumps (ideal, and quite common)
Release the PDBs (which won't contain much more info than you're already trying to deduce)
Use inline trace information in your app such as __LINE__, __FILE__, and __FUNCTION__.
Just capture the crash address if you can't piece together a meaningful stack trace.
Hope this helps!
You can get verbose output from the linker that will show you where each function is placed in the executable. Then you can use the offset from the crash report to figure out which function was executing.
In release mode, this sort of debugging information isn't included in the binary. You can't use debugging information which simply isn't there.
If you need to debug release-mode code, start manually tracing execution by writing to a log file or stdout. You can include information about where your code appears using __FUNCTION__ and __LINE__, which the compiler will replace with the function/line they appear in/on. There are many other useful predefined macros which you can use to debug your code.
Here's a very basic TR macro, which you can sprinkle through out your code to follow the flow of execution.
void trace_function(const char* function, int line) {
std::cout << "In " << function << " on line " << line << std::endl;
}
#define TR trace_function(__FUNCTION__, __LINE__)
Use it by placing TR at the top of each function or anywhere you want to be sure the flow of execution is reaching:
void my_function() {
TR();
// your code here
}
The best solution though, is to do your debugging in debug mode.
You can separate the debug symbols so that your release version is clean, then bring them together with the core dump to diagnose the problem afterwards.
This works well for GNU/Linux, not sure what the Microsoft equivalent is. Someone mentioned PDB...?

Boost serialization assertion fail

I use boost's binary serialization and it worked well until now. I have std::list of pointers to serialize for output (oarchive) but serialization fails inside object's serialize() function with MSVC's dialog:
R6010 -abort() has been called
and such string is printed into console window:
Assertion failed: 0 == static_cast<int>(t) || 1 == static_cast<int>(t), file c:\program files\boost\boost_1_44\boost\archive\basic_binary_oprimitive.hpp, line 91
what does it mean?
Project is pretty big, sources are distributed so I cannot post it's code here, but I tried to simulate this error within simple project - there it works fine what is strange.
P.S. I use boost 1.44 with MSVC2010EE on Windows XP. When I click "retry" on "Debug Error!" window debugger shows arrow on the code line next to serialization archive << myList; line - I mean it seems like error occurred at some destructor or something.
When I make changes inside objects serialize() function - they will be applied just when I rebuild whole project (clean before compiling) - but if I just compile it (where IDE shows that all sources which include changed header are recompiled) - no changes will happen at runtime since last version (I tried with printf()) - that's strange.
Could I occasionally set some critical definitions or something?
The line in question says:
// trap usage of invalid uninitialized boolean which would
// otherwise crash on load.
It looks like at some point you are trying to serialize a bool that hasn't been initialized. Without further code we can't help you find which one.

Program crashes with 0xC000000D and no exceptions - how do I debug it?

I have a Visual C++ 9 Win32 application that uses a third-party library. When a function from that library is called with a certain set of parameters the program crashes with "exception code 0xC000000D".
I tried to attach Visual Studio debugger - no exceptions are thrown (neither C++ nor structured like access violations) and terminate() is not called either. Still the program just ends silently.
How does it happen that the program just ends abnormally but without stopping in the debugger? How can I localize the problem?
That's STATUS_INVALID_PARAMETER, use WinDbg to track down who threw it (i.e. attach WinDbg, sxe eh then g.
Other answers and comments to the question helped a lot. Here's what I did.
I notices that if I run the program under Visual Studio debugger it just ends silently, but if I run it without debugger it crashes with a message box (usual Windows message box saying that I lost my unsaved data and everyone is sooo sorry).
So I started the program wihtout debugger, let it crash and then - while the message box was still there - attached the debugger and hit "Break". Here's the call stack:
ntdll.dll!_KiFastSystemCallRet#0()
ntdll.dll!_ZwWaitForMultipleObjects#20() + 0xc bytes
kernel32.dll!_WaitForMultipleObjectsEx#20() - 0x48 bytes
kernel32.dll!_WaitForMultipleObjects#16() + 0x18 bytes
faultrep.dll!StartDWException() + 0x5df bytes
faultrep.dll!ReportFault() + 0x533 bytes
kernel32.dll!_UnhandledExceptionFilter#4() + 0x55c bytes
//SomeThirdPartyLibraryFunctionAddress
//SomeThirdPartyLibraryFunctionAddress
//SomeThirdPartyLibraryFunctionAddress
//SomeThirdPartyLibraryFunctionAddress
//OurCodeInvokingThirdPartyLibraryCode
so obviously that's some problem inside the trird-party library. According to MSDN, UnhandledExceptionFilter() is called in fatal situations and clearly the call is done because of some problem in the library code. So we'll try to work the problem out with the library vendor first.
If you don't have source and debugging information for your 3rd party library, you will not be able to step into it with the debugger. As I see it, your choices are;
Put together a simple test case illustrating the crash and send it onto the library developer
Wrap that library function in your own code that checks for illegal parameters and throw an exception / return an error code when they are passed by your own application
Rewrite the parts of the library that do not work or use an alternative
Very difficult to fix code that is provided as object only
Edit You might also be able to exit more gracefully using __try __finally around your main message loop, something like
int CMyApp::Run()
{
__try
{
int i = CWinApp::Run();
m_Exitok = MAGIC_EXIT_NO;
return i;
}
__finally
{
if (m_Exitok != MAGIC_EXIT_NO)
FaultHandler();
}
}

process termination C++

I have the following problem: I have an application (server that never ends) written in C++ running as a service containing inside the main thread also 3 threads (mainly doing IO).
In the main loop I CATCH all possible exceptions.
The process terminated and nothing was printed either by the main loop or by the threads themselves. I saw in the event log that the process stopped with code 1000.
Does Windows creates Core files like in unix ?
If from the event log I get a memory address, is there any way of knowing in which part in the application it occurred?
Maybe this is a clue: at the same time that it happened I started another application (not the same type).
try to set windbg as the postmortem debugger.
install windbg
from commandline execute "windbg -I"
start you application, then you when your application get an unhandled exception,
the windbg will be activated .
from windbg use "kb" or "!uniqstack" to see the stacktrace.
look here for more commands.
and look here for how to analysis.
and try use SEH:
#include "windows.h"
#include "stdio.h"
DWORD FilterFunction()
{
printf("you will see this message first.\n");
return EXCEPTION_EXECUTE_HANDLER;
}
int main(char** argv, int c)
{
__try
{
int this_will_be_zero = (c == 9999);
int blowup = 1 / this_will_be_zero;
}
__except ( FilterFunction())
{
printf("you will see this message\n");
}
return 0;
}
Bear in mind that catch(...) does not intercept everything that can go wrong in your code, unless you are using Structured Exception Handling. Eg
#include "stdio.h"
int main(char** argv, int c)
{
try {
int this_will_be_zero = (c == 9999);
int blowup = 1 / this_will_be_zero;
} catch (...) {
printf("you won't see this message\n");
}
}
You need to use the /EHa compiler switch when building your application in order to catch windows structured exceptions (such as access violation) with the C++ try/catch constructs.
In Visual Studio this is in project properties Configuration Properties -> C/C++ -> Code Generation -> Enable C++ Exceptions. You want "Yes With SEH Exceptions (/EHa)". I remember reading setting this has some significant drawbacks, although I cannot recall what they were exactly.
Link: MSDN on C++ exception handling model
Edit: As whunmr suggests, directly using structured exceptions is probably better idea than /EHa
Does Windows creates Core files like in unix ?
it does not, automatically. however you can enable such a files by
either implementing it in your code or by using external application
as windbg, or Dr. Watson
If from the event log I get a memory address, is there any way of knowing in which part in the application it occurred?
There is no way if in general, if you don't keep debug information files (pdb)
Maybe this is a clue: at the same time that it happened I started another application (not the same type).
this is not helpful information, unless both of the applications are interacted each other
Windows will whatever program you are using as a debugger depending on the setting in:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug]
"Auto"="0"
"Debugger"="My_Debugger" -p %ld -e %ld"
"UserDebuggerHotKey"=dword:00000000
You can change My_Debugger to the full path of whatever program/IDE you are using for debugging.
This is often set to Dr Watson which will create a log entry of the crash which is not what you want.