Reputation: 582
I am new in to C++ programming. _set_invalid_parameter_handler give me function name,file and line when I pass invalid parameter to a C++ system function -for ex.:in _tmain printf line generates error-, but I want to get function name, file and line of my programming, not about system function.
void myInvalidParameterHandler(const wchar_t* expression,
const wchar_t* function,
const wchar_t* file,
unsigned int line,
uintptr_t pReserved)
{
wprintf(L"Invalid parameter detected in function %s."
L" File: %s Line: %d\n", function, file, line);
wprintf(L"Expression: %s\n", expression);
call_stack st;
st.stack.back();
cout << st.stack.back().to_string();
cout << st.to_string();
}
int _tmain(int argc, _TCHAR* argv[])
{
char* formatString;
_invalid_parameter_handler oldHandler, newHandler;
newHandler = myInvalidParameterHandler;
oldHandler = _set_invalid_parameter_handler(newHandler);
formatString = NULL;
printf(formatString); // I want to get this line
return 0;
}
in this sample myInvalidParameterHandler generates below output: function = printf, file = f:\dd\vctools\crt\crtw32\stdio\printf.c, expression = (format != NULL) , line = 54
But I want to get something like: function = _tmain , file : ...\MySample.cpp , line = (printf line in mysample.cpp) How can I do that ?(like C# stack trace) ?
I also tried stack walker (call_stack), it gives me self line and i could not get my need by this way.
EDIT : Did not answer anyone yet . PLEASE HELP. 2015.02.25 16:42 Turkiye(Athens zone)
Upvotes: 1
Views: 641
Reputation: 8148
The problem is that in C++ the callstack is not as easy available as in C#.
To get the callstack in an application which is released to the public you need the original source code, original DLL file, the original PDB file and a dump file.
You can generate a dump file in your code with MiniDumpWriteDump()
in your crash handler. But this needs a structued exception.
So you must write:
#define SEH_ARG_EXCEPTION 0xE0415247 // "ARG"
void myInvalidParameterHandler(....) // all params are NULL in a release build
{
RaiseException(SEH_ARG_EXCEPTION, EXCEPTION_NONCONTINUABLE, 0, NULL);
}
and in a structured exception handler you catch this:
__try
{
Execute your code with invalid argument
}
__except(ExceptionHandler(GetExceptionInformation()))
{
}
static int ExceptionHandler(EXCEPTION_POINTERS* pk_Ptr)
{
switch (pk_Ptr->ExceptionRecord->ExceptionCode)
{
case EXCEPTION_BREAKPOINT:
case EXCEPTION_SINGLE_STEP:
return EXCEPTION_CONTINUE_SEARCH;
}
MINIDUMP_EXCEPTION_INFORMATION k_Mini;
k_Mini.ThreadId = GetCurrentThreadId();
k_Mini.ExceptionPointers = pk_Ptr;
k_Mini.ClientPointers = FALSE;
HANDLE h_File = CreateFile(L"DumpPath\\XYZ.dmp", GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), h_File, MINIDUMP_TYPE, &k_Mini, 0, 0);
CloseHandle(h_File);
MessageBox(NULL, L"The application has crashed.\nA Minidump has been written to: XYZ.dmp\nPlease send this file to [email protected]", L"Fatal Error", MB_ICONSTOP | MB_TOPMOST);
TerminateProcess(GetCurrentProcess(), 0);
return EXCEPTION_EXECUTE_HANDLER;
}
You will then have a DMP file on disk which your user must send to you so you can load it into Visual Studio and get the crash location from the stacktrace.
Important: You need the exact original code and DLL and PDB file for this to work.
Upvotes: 1