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);
}
Related
I have a program that throws in another thread as follows:
#include <iostream>
#include <stdexcept>
#include <thread>
void op()
{
std::cout << "OP HELLO WORLD" << std::endl;
throw(std::runtime_error("OP ERROR"));
};
int main(int argc, char* argv[])
{
//throw(std::runtime_error("MAIN ERROR"));
std::thread t(op);
t.join();
std::cout << "MAIN HELLO WORLD" << std::endl;
};
I want my program to print a clear error message and stop. I know I can use std::abort or std::terminate, however the error message is not clear and does not contain the log "OP ERROR".
Could you please help me code a program that when fails exits and logs a clear error message. std::future does not work too when I tried a try, catch block?
Are you looking for something like this?
#include <iostream>
#include <stdexcept>
#include <thread>
#include <future>
void op()
{
std::cout << "OP HELLO WORLD" << std::endl;
throw(std::runtime_error("OP ERROR. File: " __FILE__ ", Line: "+ std::to_string(__LINE__)));
};
int main(int argc, char* argv[])
{
//throw(std::runtime_error("MAIN ERROR"));
auto res = std::async(op);
try {
res.get();
} catch(const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
return -1;
}
std::cout << "MAIN HELLO WORLD" << std::endl;
}
If you want to output errors for all threads without returning exceptions to main thread, you can setup your own version of terminate().
#include <iostream>
#include <cstdlib>
#include <exception>
#include <thread>
void op()
{
std::cout << "OP HELLO WORLD" << std::endl;
throw(std::runtime_error("OP ERROR"));
}
void my_terminate()
{
auto eptr = std::current_exception();
try {
if (eptr) {
std::rethrow_exception(eptr);
}
} catch(const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
}
std::abort();
}
int main(int argc, char* argv[])
{
std::set_terminate(my_terminate);
//throw(std::runtime_error("MAIN ERROR"));
std::thread t(op);
t.join();
std::cout << "MAIN HELLO WORLD" << std::endl;
}
For some reason MSVC uses per-thread handlers, and for it to work you need to call set_termnate() in every thread separatelly.
To avoid the call to std::terminate, make sure exceptions don't "leak" outside the thread function.
void op()
{
try {
std::cout << "OP HELLO WORLD" << std::endl;
throw std::runtime_error("OP ERROR");
} catch (const std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
exit(1);
}
}
If you want to automatically see the exception's file and line number, in C++ it is not generally possible.
If you want to catch all exceptions in a single place in the main thread, you need to catch them and pass them to the main thread. There's a useful wrapper utility std::packaged_task which gives back a future on which you can wait for the result or an exception.
#include <iostream>
#include <stdexcept>
#include <thread>
#include <future>
void op()
{
std::cout << "OP HELLO WORLD" << std::endl;
throw std::runtime_error("OP ERROR");
}
int main(int argc, char* argv[])
{
try {
std::packaged_task<void()> task{&op};
auto result = task.get_future();
std::thread t{std::move(task)};
t.join();
result.get();
std::cout << "MAIN HELLO WORLD" << std::endl;
} catch (const std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
}
}
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.
I am new to C++ and wondering how I could catch all possible errors that could happen in my program during run-time. This is for debugging reasons only. To solve possible errors, I would like to have a look at them first.
This would be my idea of how to catch possible errors in a program. I do not throw exceptions, but would like to catch possible errors directly.
#include <iostream>
#include <exception>
#include <stdexcept>
int doBadStuf(int i)
{
// go out of bounce, or make other mistakes
return 10 / i;
}
int main()
{
try
{
int i = doBadStuf(0);
}
catch (std::exception &e)
{
std::cerr << e.what() << '\n';
}
catch (...)
{
std::cerr << "something else";
}
}
I'm working on a fairly lengthy program, and after running fine for awhile, suddenly I'm getting:
terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::substr
Being new to exception handling, I did some research and found that I would likely get more information by adding the following to my main function:
int main(int argc, char **argv){
try{
//stuff
}
catch(exception const &exc){
cerr << "Caught exception: " << exc.what() << endl;
}
}
The result of this is the following output:
Caught exception: basic_string::substr
This isn't any more useful than the default output; it doesn't tell me anything about the line triggering the core dump (there are many substr calls in my program), the data the substr is attempting to process, etc. Is there a method for displaying information such as this in C++, or is my only option to use a debugger such as gdb?
There are a few ways.
As you said, a debugger - but that won't help you once the code is in production.
Nested exceptions and function try blocks. e.g.:
#include <exception>
#include <stdexcept>
#include <iostream>
#include <sstream>
#include <iomanip>
void bar(std::string& s, int i)
try
{
s.at(i) = 'A';
}
catch(...)
{
std::ostringstream ss;
ss << "error in bar(" << std::quoted(s) << ", " << i << ")";
std::throw_with_nested(std::runtime_error(ss.str()));
}
void foo(std::string& s)
try
{
bar(s, 6);
}
catch(...)
{
std::ostringstream ss;
ss << "error in foo(" << std::quoted(s) << ")";
std::throw_with_nested(std::runtime_error(ss.str()));
}
void stuff()
try
{
std::string s;
foo(s);
}
catch(...)
{
std::throw_with_nested(std::runtime_error("error in stuff()"));
}
void print_exception(std::ostream& os, const std::exception& e, int level = 0)
{
os << std::string(level, ' ') << "exception: " << e.what() << '\n';
try {
std::rethrow_if_nested(e);
} catch(const std::exception& e) {
print_exception(os, e, level+1);
} catch(...) {}
}
int main()
{
try{
stuff();
}
catch(std::exception& e)
{
print_exception(std::cerr, e);
return 127;
}
return 0;
}
sample output:
exception: error in stuff()
exception: error in foo("")
exception: error in bar("", 6)
exception: basic_string::at: __n (which is 6) >= this->size() (which is 0)
You could use boost::stacktrace in place of the above nested exception handling.
http://coliru.stacked-crooked.com/a/f21bd35632a0a036
I have a program throwing an exception that is caught on some configurations (Suse Linux, g++ version 4.4.1) as expected but is obviously not caught on another, here: SunOS 5.10, g++ version 3.3.2. Following is the implementation of my exception class:
CException.hpp:
#ifndef _CEXCEPTION_HPP
#define _CEXCEPTION_HPP
#include <string>
#include <sstream>
#include <exception>
#include <stdlib.h>
#include <iostream>
class CException : public std::exception {
public:
CException();
CException(const std::string& error_msg);
CException( const std::stringstream& error_msg );
CException( const std::ostringstream& error_msg );
virtual ~CException() throw();
const char* what() const throw();
static void myTerminate()
{
std::cout << "unhandled CException" << std::endl;
exit(1);
};
private:
std::string m_error_msg;
};
CException.cpp:
#include "CException.hpp"
#include <string>
#include <sstream>
CException::CException()
{
std::set_terminate(myTerminate);
m_error_msg = "default exception";
}
CException::CException(const std::string& error_msg)
{
std::set_terminate(myTerminate);
m_error_msg = error_msg;
}
CException::CException(const std::stringstream& error_msg)
{
std::set_terminate(myTerminate);
m_error_msg = error_msg.str();
}
CException::CException(const std::ostringstream& error_msg)
{
std::set_terminate(myTerminate);
m_error_msg = error_msg.str();
}
CException::~CException() throw()
{
}
const char* CException::what() const throw()
{
return m_error_msg.c_str();
}
#endif /* _CEXCEPTION_HPP */
Unfortunately, I've not been able to create a simple program to reproduce the issue, but I will try to outline the code.
The exception is thrown in a function foo() in some file Auxiliary.cpp:
std::ostringstream errmsg;
//...
errmsg << "Error occured.";
throw CException( errmsg );
Function foo() is used in the main program:
#include Auxiliary.hpp
//...
int main( int argc, char** argv )
{
try {
//...
foo();
} catch ( CException e ) {
std::cout << "Caught CException" << std::endl;
std::cout << "This is the error: " << e.what( ) << std::endl;
} catch ( std::exception& e ) {
std::cout << "std exception: " << e.what( ) << std::endl;
} catch ( ... ) {
std::cout << "unknown exception: " << std::endl;
}
I can see that the exception isn't caught as the program exits with printing unhandled CException which is defined by myTerminate().
I've tried the -fexceptions option to the GNU compiler without success. The compiler options are actually the same on both systems.
At the moment I just can't figure out what the problem is. Any ideas are appreciated. Thanks!
I've found out that the problem is caused by the use of a Fortran95 compiler. It is used as a linker when building the program on a Sun machine, on other machines g++ is used. I have no idea what exactly the problem is but I think I'll just switch to g++ on the Sun machines as well.