Visual studio is hiding my exception messages. Take the following code example:
#include <stdio.h>
#include <iostream>
#include <exception>
void exceptional_method(){
throw std::runtime_error("Hello from exceptional_method!");
}
int main(){
std::cout << "Hello world!" << std::endl;
exceptional_method();
std::cin.get();
}
Visual studio gives me some vague addresses:
Unhandled exception at 0x76A9DDC2 in ExceptionTest.exe: Microsoft C++ exception: std::runtime_error at memory location 0x006FFD34.
Whereas linux mint gives me the following output on the terminal:
Hello world!
terminate called after throwing an instance of 'std::runtime_error'
what(): Hello from exceptional_method!
Aborted (core dumped)
I've googled a bunch, messed around with the settings in Visual studio, but cannot figure this out. My current workaround is writing the exception message to console before throwing so that I can at least catch the message so I know which exception was thrown.
inline void throw_exception(string& message)
{
cout << message << endl;
throw runtime_error(message);
}
This is not ideal. Any help would be greatly appreciated.
edit:
Getting the debugger to break on the actual exception instead of a few lines ahead was the problem, causing me to investigate the wrong code.
The following solution is what I was looking for.
#ifndef DEBUG_ASSERT_H
#define DEBUG_ASSERT_H
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;
inline void log_failed_assert(const string message, const string expression, const string file, const long line) {
cout << "Assert failed." << endl;
cout << "Expression: " << expression << endl;
cout << "Message : " << message << endl;
cout << "File : " << file << endl;
cout << "Line : " << line << endl;
}
inline void windows_break()
{
#ifdef _WIN32
__debugbreak();
#endif
}
//do {
//} while (0)
#ifdef _DEBUG
#ifdef _WIN32
#define DEBUG_ASSERT(expr, s) do{\
if(!(expr)){\
log_failed_assert(s, #expr, __FILE__, __LINE__);\
__debugbreak();\
}\
} while(0)
#else
#define DEBUG_ASSERT(expr, s) do{\
if(!(expr)){\
log_failed_assert(s, #expr, __FILE__, __LINE__);\
}\
} while(0)
#endif
#else
#define DEBUG_ASSERT(expr, s)
#endif
#endif
Exceptions are there to be catched. If you dont catch it your program will terminate. If this is what you want, there are easier ways to terminate. If you catch the exception in main you can use the message to eg print it:
#include <exception>
#include <iostream>
void exceptional_method(){
throw std::runtime_error("Hello from exceptional_method!");
}
int main(){
std::cout << "Hello world!" << std::endl;
try {
exceptional_method();
} catch (std::exception& e) {
std::cout << e.what();
}
std::cin.get();
}
As RichardCritten pointed out, it is mint being nice to you rather than visual studio "hiding" the message, as there is no requirement to print the message when your program terminates.
Related
I am working on program that uses a DLL library (LibPlcTag : https://github.com/libplctag/libplctag) and I wanted to add some exception handling to 'my' code. However after finding this was not working, that is the thrown exceptions were not being caught, I managed to distill it all down to the following bit of demonstration code.
So the question is what is going on here ? Why does a call to a DLL function kill C++ try catch ? Is there a way to fix this ?
FYI : I am using Mingw32 C++ with -std=c++11 compiler build flag on Windows 11.
#include <iostream>
#define SHOWERROR 1
#if SHOWERROR
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllimport) int plc_tag_check_lib_version(int req_major, int req_minor, int req_patch);
#ifdef __cplusplus
}
#endif
#endif
int main(int argc, char *argv[])
{
#if SHOWERROR
std::cout << "Call DLL function" << std::endl;
plc_tag_check_lib_version(0,0,0);
std::cout << "Call Finished" << std::endl;
#else
std::cout << "No DLL Function Call !!" << std::endl;
#endif
try
{
std::cout << "Throw error" << std::endl;
throw "Error";
}
catch( ... )
{
std::cout << "Exception happened" << std::endl;
}
std::cout << "End" << std::endl;
return 0;
}
With SHOWERROR = 0 the exception is caught :
No DLL Function Call !!
Throw error
Exception happened
End
C:\...\test>
But with SHOWERROR = 1 the exception is not caught and the program terminates without printing 'End' :
Call DLL function
Call Finished
Throw error
C:\...\test>
After working on the hunch that my build LibPlcTag was broken in some way I went back to the beginning and instead of using the MinGW32 (5.1.0) that was installed by PlatformIO for 'platform = windows_x86' I installed MSYS2 and the mingw-w64-i686-toolchain.
I then re-built the LibPlcTag library to get a new DLL.
I then used the mingw toolchain above to rebuild the my test app. Now it works and the exception is caught.
The final test code :
#include <iostream>
#include <fstream>
#define SHOWERROR 1
#if SHOWERROR
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllimport) int plc_tag_check_lib_version(int req_major, int req_minor, int req_patch);
#ifdef __cplusplus
}
#endif
#endif
// void not_called()
// {
// std::cout << "Call DLL function" << std::endl;
// #if SHOWERROR
// plc_tag_check_lib_version(0,0,0);
// #endif
// std::cout << "Call Finished" << std::endl;
// }
int main(int argc, char *argv[])
{
#if SHOWERROR
std::cout << "Call DLL function" << std::endl;
plc_tag_check_lib_version(0,0,0);
std::cout << "Call Finished" << std::endl;
#else
std::cout << "No DLL Function Call !!" << std::endl;
#endif
try
{
std::cout << "Throw error" << std::endl;
throw "Error";
}
catch( ... )
{
std::ofstream debugFile("debug.txt");
debugFile << "Exception happened" << std::endl;
debugFile.close();
std::cout << "Exception happened" << std::endl;
}
std::cout << "End" << std::endl;
return 0;
}
And output :
Call DLL function
Call Finished
Throw error
Exception happened
End
C:\...\test>
Thank you to those that contributed the above thoughtful comments...
I have problem when I use csignal.
I use Visual Studio 2019
#include <Windows.h>
#include <csignal>
#include <iostream>
void signalHandler(int signum)
{
std::cout << "Interrupt signal (" << signum << ") received.\n";
exit(signum);
}
int main()
{
std::signal(SIGINT, signalHandler);
while (1)
{
std::cout << "Going to sleep...." << std::endl;
Sleep(1);
raise(0);
}
std::cout << "Hello World!\n";
return 0;
}
when raise called after I had:
I have ucrtbased.dll in:
C:\Windows\System32
I installed Windows SDK. I don't understand what is wrong?
You're raising signal 0 (raise(0);) which is probably an invalid signal value.
You should use the standard #defines (which may have compiler-specific values) for parameter (see spec).
I have tried to create a program in C++ that can catch and handle bad_alloc exception.
While writing the code, I have noticed no errors but when I have tried to compile this code I got C2276 error code and C3876 in Microsoft Visual Studio Community 2017.
The error itself seems to appear in the catch{...} code block.
#include "pch.h"
#include <iostream>
#include <string>
using namespace std;
class CanGoWrong {
public:
CanGoWrong() {
char *pMemory = new char[9999999999];
delete[] pMemory;
}
};
int main()
{
try {
CanGoWrong wrong;
}
catch(std::bad_alloc &e){
cout << "Caught exception: "<< e.what << e << endl;
}
cout << "Still running" << endl;
return 0;
}
The error with code C3867 ("non standart syntax, use &") I fixed this way :
from
cout << "Caught exception: "<< e.what << e << endl;
to:
cout << "Caught exception: "<< &e.what << e << endl;
Still, the error C2276 won't disappear. I guess there is something to do using basic std::exception class.
I want to understand how to do it right, this code is an course sample that I must follow and understand.
When printing what() from a Windows console app, it works in English but running it in Korean for instance the output is all question marks like:
"?????? ???????????????."
The below code is what I have tried.
#include <iostream>
#include <windows.h>
int wmain(void)
{
try
{
throw std::system_error(ERROR_ACCESS_DENIED, std::system_category());
}
catch (const std::system_error &e)
{
std::wcout << e.what() << std::endl;
}
return(0);
}
I'm trying to use a macro to queue up a single log line locally in an ostringstream and then dump the entire contents of that ostringstream when the line is over. I want to still use stream insert syntax, however. So I want to turn a log line like this:
std::cerr << "Some error in my function. Code is " << errCode << " exiting" << std::endl;
...into this
SERR("Some error in my function. Code is " << errCode << " exiting);
I've got something simple that works well. That is, until I put it in an if-else statement. Obviously my macro is bad but I am at a loss as to what to do.
Here is a small sample program, hacked up to illustrate the problem.:
#include <iostream>
#include <sstream>
#define SERR(x) { std::ostringstream _s; ; _s << x << std::endl; std::cerr << _s.str(); }
int main()
{
std::cout << "Hello World!\n";
bool val = false;
if (val)
SERR("No error");
else
SERR("Error");
}
The error message I get from the compiler in this sample is:
1>c:\users\joe\source\repos\consoleapplication5\consoleapplication5\consoleapplication5.cpp(15):
error C2181: illegal else without matching if
Any ideas what I've got wrong here?
(Note I'm not in a place where I can use a 3rd Party logging solution now so it's got to be something simple like this. I could just leave all this as normal std::cerr/std::cout/std::clog messages, if I had to but I'd prefer something simple to minimize the chances of interleaving of log messages from my multithreaded app.)
Just try to expand it and see what you get:
#include <iostream>
#include <sstream>
int main()
{
std::cout << "Hello World!\n";
bool val = false;
if (val)
{ std::ostringstream _s; ; _s << "No error" << std::endl; std::cerr << _s.str(); };
else
{ std::ostringstream _s; ; _s << "Error" << std::endl; std::cerr << _s.str(); };
}
Notice how { } block is terminated with ;?
If you need a macro, you should always write it using do { } while (0) like this:
#define SERR(x) \
do { \
std::ostringstream _s; \
_s << (x) << std::endl; \
std::cerr << _s.str(); \
} while (0)
Not only this solves your issue, but also make it mandatory to add ; after the macro. Otherwise people could use it two ways:
SERR("foo") // without ;
...
SERR("bar"); // with ;