I have a shared_ptr in C++ that I want to throw as an exception. I was writing a test case that used an equivalent situation to this in gcc 6.4.0 and got stuck.
I don't understand why x is NULL after the exception has been handled, even though it hasn't gone out of scope or been assigned to.
#include "stdafx.h"
#include <iostream>
#include <memory>
#include <string>
using namespace std;
class S {
private:
string s;
public:
string String()
{
return s;
}
S(string a) : s(a)
{
cout << "S::S( " << a << " )" << endl;
}
~S()
{
cout << "S::~S( " << String() << " )" << endl;
}
};
int main(int argc, char* argv[])
{
shared_ptr< S > x = make_shared<S>("hello world");
cout << "Before throw" << endl;
try {
throw x;
}
catch (shared_ptr<S> e) {
cout << "Caught it!" << endl;
if (e) {
cout << e->String() << endl;
}
}
cout << "After throw" << endl;
if (!x) {
cout << "X is Null" << endl;
}
cout << "I'm done" << endl;
return 0;
}
Visual Studio 2013 does what I expect:
S::S( hello world )
Before throw
Caught it!
hello world
After throw
I'm done
S::~S( hello world )
but GCC 6.4.0 (from Cygwin) does not:
S::S( hello world )
Before throw
Caught it!
hello world
S::~S( hello world )
After throw
X is Null
I'm done
Is there something going on here that I don't understand that makes GCC's behavior legal? Can I make it work in gcc as I intended?
[This is the same gcc bug as referred to in the question mentioned in the comments. I was hoping for a way to continue test case development for my project. The solution I found was to put the "try/catch" inside of separate function that took x as a parameter.]
[The bug is more subtle than it seems. If you add "swap(x, e);" inside the exception handler, after the handler returns, x is not longer empty but e is null within the handler. I was trying to save the S instance and to understand the situation better. When I added that swap, not only was x not empty at the end (which I expected), e was null after the swap which was completely unexpected. Adding the swap changed the output to
S::S( hello world )
Caught it!
S::~S( hello world )
It's not obvious why swapping two things that should be the same does that.]