Missing destructor in Visual Studio? - c++

I wrote the following program:
// Example program
#include <iostream>
#include <string>
#include <exception>
struct A {
A() {
std::cout << "A ctor" << std::endl;
}
~A() {
std::cout << "A dtor" << std::endl;
try {
throw std::exception();
} catch (std::exception &e) {
std::cout << "Internal exception caught" << std::endl;
}
}
};
int main()
{
try {
A a;
throw std::exception();
} catch (std::exception &e) {
std::cout << "External exception caught" << std::endl;
}
}
The output I expected was:
A ctor
A dtor
Internal exception caught
External exception caught
And this is what I'm getting in GCC. But when I'm using Visual Studio (version 2013) the output I'm getting is:
A ctor
External exception caught
What's going on here?

MSVC2013 is wrong here and GCC is right. Unfortunately, I cannot find an appropriate reference from the standard now, but according to std::uncaught_exception:
For example, if stack unwinding causes a stack-allocated object to be
destructed, the destructor for that object could run code that throws
an exception as long as the exception is caught by some catch block
before escaping the destructor.
For more details see also "Throwing during stack unwinding" section here.
Finally, as it is mentioned by #StoryTeller, this behaviour is not reproducible with newer MSVC versions.
The closest match in the standard I am able to find is the next (from the N3936 draft):
15.1 Throwing an exception [except.throw]
If the exception handling mechanism, after completing the
initialization of the exception object but before the activation of a
handler for the exception, calls a function that exits via an
exception, std::terminate is called.
So, formally, it is perfectly valid to call a function during stack unwinding process (including destructor) which might deal with exception, but if the exception inside such function is not caught by appropriate catch block then std::terminate must be called.

Related

Why does iostream require the exception handler to be called while using vcvarsall.bat to compile 'Hello World'?

Attempting to compile the following code with vcvarsall.bat in command line throws a warning saying that the exception handler is needed in the code but not called before using /EHsc.
Code:
#include <iostream>
int main()
{
std::cout << "hello world" << std::endl;
return 0;
}
The batch file:
#echo off
cl C:\Development\..\basicmath.cpp
The warning:
C:\...\ostream(746): warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
C:...\basicmath.cpp(10): note: see reference to function template instantiation 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const char *)' being compiled
Line 743 - 754 of ostream line 746 (from error) is _TRY:
if (!_Ok) {
_State |= ios_base::badbit;
} else { // state okay, insert
_TRY_IO_BEGIN
if ((_Ostr.flags() & ios_base::adjustfield) != ios_base::left) {
for (; 0 < _Pad; --_Pad) { // pad on left
if (_Traits::eq_int_type(_Traits::eof(), _Ostr.rdbuf()->sputc(_Ostr.fill()))) {
_State |= ios_base::badbit; // insertion failed, quit
break;
}
}
}
Adding /EHsc to my batch file will allow it to run but I would like to know why this is. Why does this block of code from the file for output require EHsc to be called?
MSDOCS says EHsc is for cleanup to prevent memory leaks, what is causing the leak and why do they need an external program to fix the leak instead of fixing it in the same file (this may sound rude but its just ignorant)?
Edit: thank you for pointing out its a warning and not an error.
Short answer:
Add /EHs or /EHsc to your compilation options as the documentation suggests. It's the most portable option regarding exceptions handling, if you will ever need to execute the same code on Unix machine.
Long answer:
There are two parts to this question. First is why the warning occurs in iostream and the second is what does the warning mean.
Why are there exceptions in iostream?
The default behaviour of streams in C++ is exceptionless - any failure is represented by setting an internal fail bit, accessible with eof(), fail() and bad() functions. However, you can change this behaviour to throwing exceptions on failure by using exceptions() method on stream. You can choose which fail bits trigger exceptions, but the main point is that the code must be there by standard. The warning seems to analyze only that - it notices a possible path where throw occurs and reports a warning.
What does the warning mean?
From the Microsoft documentation (emphasis mine):
By default (that is, if no /EHsc, /EHs, or /EHa option is specified), the compiler supports SEH handlers in the native C++ catch(...) clause. However, it also generates code that only partially supports C++ exceptions . The default exception unwinding code doesn't destroy automatic C++ objects outside of try blocks that go out of scope because of an exception.
The issue is that (for some reason) MSVC compiler by default generates assembly which is wrong according to the standard. Stack unwinding will not be perfomerd when exception is thrown, which may cause memory leaks and other unexpected behaviours.
An example correct C++ code, which has a memory leak under the default setting:
void foo()
{
std::string str = "This is a very long string. It definitely doesn't use Small String Optimization and it must be allocated on the heap."
std::cout << str;
throw std::runtime_error{"Oh no, something went wrong"};
}
int main()
{
try
{
foo();
}
catch (std::exception&)
{
// str in foo() was possibly not released, because it wasn't deleted when exception was thrown!
}
}
So the final answer would be:
If you plan to use Structured Exceptions (like divide-by-zero or invalid memory access errors) or use a library that uses them, use /EHa
If you don't need to catch SEs, choose /EHs for compatibility with C++ standard and portability
Never leave the defaults, always set /EH to one alternative or another, otherwise you will have to deal with strange behaviours when using exceptions.
That's a warning so your current program compiles fine. But problems come up in programs as such:
#include <exception>
#include <iostream>
struct A{
A(int x):x(x) {
std::cout<<"Contructed A::"<<x<<'\n';
}
~A() {
std::cout<<"Destructed A::"<<x<<'\n';
}
private:
int x;
};
void foo() {
A a{2};
throw std::bad_exception{};
}
int main()
{
A a {1};
try {
foo();
} catch(const std::bad_exception& ex) {
std::cout<<ex.what()<<'\n';
}
return 0;
}
Using cl test.cpp yields the output:
Contructed A::1
Contructed A::2
bad exception
Destructed A::1
While using cl test.cpp /EHsc yields:
Contructed A::1
Contructed A::2
Destructed A::2
bad exception
Destructed A::1
This behavior is explained by the documentation for the warning C4530:
When the /EHsc option isn't enabled, automatic storage objects in the
stack frames between the throwing function and the function where the
exception is caught don't get destroyed. Only the automatic storage
objects created in a try or catch block get destroyed, which can lead
to significant resource leaks and other unexpected behavior.
That explains a {2} not being destructed when the program wasn't compiled with /EHsc.
And of course,
If no exceptions can possibly be thrown in your executable, you may
safely ignore this warning.
So, for a program like
#include <cstdio>
int main()
{
std::printf("hello world\n");
return 0;
}
cl.exe quietly compiles.

How to pass C++ exceptions through functions compiled with LibJIT?

I'm using LibJIT to JIT-compile a programming language. My compiler is written in C++, so I have a C++ program calling the LibJIT library, which is written in C.
In my C++ code I have some functions that throw exceptions, and sometimes these get triggered on the far side of a LibJIT-compiled function. That is, my C++ program uses LibJIT to compile a function, calls it, and the JIT-compiled function in turn calls a C++ function that throws an exception. But instead of the exception being propagated back through the JIT-compiled function to my handler, the runtime calls std::terminate.
Apparently the exception-handling mechanism needs each function in the call stack to implement some kind of exception support. When compiling C code, the -fexceptions flag tells the compiler (at least gcc) to include this support.
Is there a way to include this exception support in my LibJIT-generated functions?
I tried using the LibJIT instructions to set up a "catcher" block that rethrows all exceptions, but that didn't work; it looks like the LibJIT's exception-handling model is separate from the C++ model.
Obviously I don't really want to throw C++ exceptions into my language's code, and I'll have to figure out some other error-handling strategy. But I'm wondering if it's even possible to get it to work.
Here's a sample program that demonstrates the issue. I'm sorry it's this long but LibJIT is pretty low-level so you have to write a lot of code to get anything done. I'm compiling on Linux with clang 10.0.0.
#include <array>
#include <exception>
#include <iostream>
#include <string>
#include <jit/jit.h>
class ex : public std::exception {};
extern "C" int bad(int arg) {
std::cout << "Called with arg=" << arg << std::endl;
throw ex();
}
jit_function_t build_function(jit_context_t context) {
// The signature of the compiled function and "bad" are the same.
std::array<jit_type_t, 1> params{jit_type_int};
jit_type_t signature = jit_type_create_signature(jit_abi_cdecl, jit_type_int, params.data(), params.size(), 1);
jit_function_t function = jit_function_create(context, signature);
jit_value_t arg_value = jit_value_get_param(function, 0);
jit_value_t bad_value =
jit_value_create_nint_constant(function, jit_type_void_ptr, (reinterpret_cast<jit_nint>(bad)));
std::array<jit_value_t, 1> bad_args{arg_value};
jit_value_t result = jit_insn_call_indirect(function, bad_value, signature, bad_args.data(), bad_args.size(), 0);
jit_insn_return(function, result);
jit_function_compile(function);
return function;
}
int main(int argc, char* argv[]) {
// This exception will be caught:
try {
bad(7);
} catch (const ex&) {
std::cout << "Caught exception from direct call" << std::endl;
}
// Initialize libjit.
// We're single-threaded so not going to bother with jit_context_build_start/jit_context_build_end.
jit_init();
jit_context_t context = jit_context_create();
jit_function_t function = build_function(context);
// This one will not be caught, calls std::terminate instead:
try {
int (*closure)(int) = reinterpret_cast<int (*)(int)>(jit_function_to_closure(function));
closure(7);
} catch (const ex&) {
std::cout << "Caught exception from libjit call" << std::endl;
}
return 0;
}
Output:
Called with arg=7
Caught exception from direct call
Called with arg=7
terminate called after throwing an instance of 'ex'
what(): std::exception
Aborted

How to get IO error messages when creating a file in C++?

One of the ancient anti-pattern is people checking error status and then returning fairly useless messages like "operation failed" instead of "operation failed because ...". I want C++ file I/O operations to fail with exception and get the error message on why it failed. Specifically I want ofstream object to raise exception when file creation fails and get bit more useful message such as "permission denied" or "No file or path".
This is trivial to do in languages such as C# or Java or Python but somehow there is no well documented way to do this C++. By default, iostream objects just fail silently. There is some global errorcode that gets but I would rather have exceptions. After lot of searching, I read that you can enable exceptions using following line of code:
my_file.exceptions(flog.exceptions() | std::ios::failbit | std::ifstream::badbit);
That works but now the exception that gets raised is std::ios_base::failure and the ex.what() returns useless strings like "basic_ios::clear". As per the C++11 specs std::ios_base::failure was supposed to be inherited from system_error which has .code().message() that will give the exception message. Let's keep aside this weirdness here and not finger point to person who decided what() should not be returning actual error message :). The problem is that even when compiling with C++11 and G++ 4.8.4, I find that std::ios_base::failure is not actually inherited from system_error.
Questions
Why std::ios_base::failure is not inherited from system_error in latest G++ 4.8.4 even when compiling with C++11 mode? Is GCC's implementation of C++11 incomplete in this area or do I need to do something more?
How do I get to my goal of raising exceptions when IO operations fail in C++ and getting error messages? Is there no way to do this even in latest C++11 or C++14? What are the alternatives?
Here's the sample code. You can compile and run it here.
#include <iostream>
#include <fstream>
#include <system_error>
int main() {
try {
std::ofstream flog;
flog.exceptions(flog.exceptions() | std::ios::failbit | std::ifstream::badbit);
flog.open("~/watever/xyz.tsv", std::ios::trunc);
}
catch (const std::ios_base::failure &ex) {
std::cout << "ios_base::failure: " << ex.what();
}
catch(const std::system_error& ex) {
std::cout << "system_error: " << ex.code().message();
}
}
According to GCC's C++11 status documentation, "System error support" is fully supported.
And according to Bug 57953 - no C++11 compliant std::ios_base::failure found, std::ios_base::failure was changed in Revision 217559 to derive from system_error in C++11. If you look in the updated ios_base.h, std::ios_base::failure derives from system_error if _GLIBCXX_USE_CXX11_ABI is defined. That define is mentioned in GCC's Using Dual ABI documentation.
However, there is a regression regarding ABI issues with std::ios_base::failure that is still open, due to the fact that some pieces of the standard library do not define _GLIBCXX_USE_CXX11_ABI:
Bug 66145 - [5/6/7 Regression] std::ios_base::failure objects thrown from libstdc++.so use old ABI
the short answer is - you probably can't, at least not with GCC's current implementation anyway. Unless you can recompile everything in the library with _GLIBCXX_USE_CXX11_ABI defined.
On POSIX systems ios failures set errno so you can get meaningful error messages using that. I often do this:
std::string getenv_as_string(std::string const& var)
{
auto ptr = std::getenv(var.c_str());
return ptr ? ptr : "";
}
// ~ doesn't work from C++
const std::string HOME = getenv_as_string("HOME");
int main()
{
try
{
std::ofstream ifs;
ifs.open(HOME + "/watever/xyz.tsv", std::ios::trunc);
if(!ifs)
throw std::runtime_error(std::strerror(errno));
// Do stuff with ifs
}
catch(std::exception const& e)
{
std::cerr << e.what() << '\n';
}
}
Output:
No such file or directory

Compiler/platform handling of buggy std::terminate() handlers

While reviewing bit of code, I came across a buggy std::terminate() handler
that wasn't terminating the program, but returning. Based on the documentation for std::set_terminate(), I think this falls within the realms of undefined - or at least implementation defined - behaviour.
Under Linux, and compiled using GCC, I found that cores were being dumped, which implies that some guardian angel was calling abort() or something similar on our behalf.
So I wrote the following test snippet, which confirmed my hunch. It looks like GCC or it's std library does wrap std::terminate() handlers so they do terminate the program.
#include <iostream>
#include <exception>
#include <dlfcn.h>
// Compile using
// g++ main.cpp -ldl
// Wrap abort() in my own implementation using
// dlsym(), so I can see if GCC generates code to
// call it if my std::terminate handler doesn't.
namespace std
{
void abort()
{
typedef void (*aborter)();
static aborter real_abort = 0x0;
if (0x0 == real_abort)
{
void * handle = 0x0;
handle = dlsym(RTLD_NEXT, "abort");
if (handle)
{
real_abort = (aborter )(handle);
}
}
std::cout << "2. Proof that GCC calls abort() if my buggy\n"
<< " terminate handler returns instead of terminating."
<< std::endl;
if (real_abort)
{
real_abort();
}
}
}
// Buggy terminate handler that returns instead of terminating
// execution via abort (or exit)
void buggyTerminateHandler()
{
std::cout << "1. In buggyTerminateHandler." << std::endl;
}
int main (int argc, char ** argv)
{
// Set terminate handler
std::set_terminate(buggyTerminateHandler);
// Raise unhandled exception
throw 1;
}
That a compiler (or library) would wrap std::terminate() handlers seems sensible to be, so at a guess I'd assume that most compilers do something along these lines.
Can anyone advise regarding the behaviour on Windows using Visual Studio or OS X using GCC?

Something unexpected happened

I'm trying to play with handling unexpected exceptions, but cannot make it to work. This is example from: C++ Reference
// set_unexpected example
#include <iostream>
#include <exception>
using namespace std;
void myunexpected () {
cerr << "unexpected called\n";
throw 0; // throws int (in exception-specification)
}
void myfunction () throw (int) {
throw 'x'; // throws char (not in exception-specification)
}
int main (void) {
set_unexpected (myunexpected);
try {
myfunction();
}
catch (int) { cerr << "caught int\n"; }
catch (...) { cerr << "caught other exception (non-compliant compiler?)\n"; }
return 0;
}
They say that output should be:
Output:
unexpected called
caught int
Which doesn't happen when I try it. My output is:
caught other exception (non-compliant compiler?)
I'm using VS2010 sp1
Documentation of unexpected says:
The C++ Standard requires that unexpected is called when a function throws an exception that is not on its throw list. The current implementation does not support this.
So the answer is that VC10 is a non-compliant compiler.
Visual Studio does not implement the standard correctly. See this MSDN page. The int is parsed, but not used.
Visual C++ always issues Warning C4290 when function has exception specifiers. From the same article in MSDN: "A function is declared using exception specification, which Visual C++ accepts but does not implement." So, this compiler does not comply with standard.