Destruction of return value on destructor exception

Clash Royale CLAN TAG#URR8PPP
up vote
25
down vote
favorite
I have the following code:
#include <stdexcept>
#include <iostream>
struct ok
int _n;
ok(int n) : _n(n) std::cerr << "OK" << n << " born" << std::endl;
~ok() std::cerr << "OK" << _n << " gone" << std::endl;
;
struct problematic
~problematic() noexcept(false) throw std::logic_error("d-tor exception");
;
ok boo()
ok ok11;
problematic p;
ok ok22;
return ok3; // Only constructor is called...
int main(int argc, char **argv)
try boo(); catch(...)
I see that he destructor of ok3 is not called, the output is:
OK1 born
OK2 born
OK3 born
OK2 gone
OK1 gone
Is it the expected behavior for C++14?
EDITs:
Compiling with gcc 6.3
c++ exception c++14 destructor object-lifetime
 |Â
show 2 more comments
up vote
25
down vote
favorite
I have the following code:
#include <stdexcept>
#include <iostream>
struct ok
int _n;
ok(int n) : _n(n) std::cerr << "OK" << n << " born" << std::endl;
~ok() std::cerr << "OK" << _n << " gone" << std::endl;
;
struct problematic
~problematic() noexcept(false) throw std::logic_error("d-tor exception");
;
ok boo()
ok ok11;
problematic p;
ok ok22;
return ok3; // Only constructor is called...
int main(int argc, char **argv)
try boo(); catch(...)
I see that he destructor of ok3 is not called, the output is:
OK1 born
OK2 born
OK3 born
OK2 gone
OK1 gone
Is it the expected behavior for C++14?
EDITs:
Compiling with gcc 6.3
c++ exception c++14 destructor object-lifetime
2
Compiler and version? Doesn't happen with cl v19.16.26926
â Swordfish
1 hour ago
@Someprogrammerdude What do you expect to not happen? Objects are expected to not be destructed, now?
â curiousguy
1 hour ago
3
eel.is/c++draft/except.ctor#2 ??
â Swordfish
1 hour ago
3
"If an exception is thrown from a destructor of a local variable or of a temporary used in a return statement, the destructor for the object returned from the function is also invoked. (since C++14)" en.cppreference.com/w/cpp/language/throw
â Mat
1 hour ago
3
This is defect #2176. The fix may not have made it into 6.3.
â molbdnilo
1 hour ago
 |Â
show 2 more comments
up vote
25
down vote
favorite
up vote
25
down vote
favorite
I have the following code:
#include <stdexcept>
#include <iostream>
struct ok
int _n;
ok(int n) : _n(n) std::cerr << "OK" << n << " born" << std::endl;
~ok() std::cerr << "OK" << _n << " gone" << std::endl;
;
struct problematic
~problematic() noexcept(false) throw std::logic_error("d-tor exception");
;
ok boo()
ok ok11;
problematic p;
ok ok22;
return ok3; // Only constructor is called...
int main(int argc, char **argv)
try boo(); catch(...)
I see that he destructor of ok3 is not called, the output is:
OK1 born
OK2 born
OK3 born
OK2 gone
OK1 gone
Is it the expected behavior for C++14?
EDITs:
Compiling with gcc 6.3
c++ exception c++14 destructor object-lifetime
I have the following code:
#include <stdexcept>
#include <iostream>
struct ok
int _n;
ok(int n) : _n(n) std::cerr << "OK" << n << " born" << std::endl;
~ok() std::cerr << "OK" << _n << " gone" << std::endl;
;
struct problematic
~problematic() noexcept(false) throw std::logic_error("d-tor exception");
;
ok boo()
ok ok11;
problematic p;
ok ok22;
return ok3; // Only constructor is called...
int main(int argc, char **argv)
try boo(); catch(...)
I see that he destructor of ok3 is not called, the output is:
OK1 born
OK2 born
OK3 born
OK2 gone
OK1 gone
Is it the expected behavior for C++14?
EDITs:
Compiling with gcc 6.3
c++ exception c++14 destructor object-lifetime
c++ exception c++14 destructor object-lifetime
edited 1 hour ago
asked 1 hour ago
Evgeny
1,0141221
1,0141221
2
Compiler and version? Doesn't happen with cl v19.16.26926
â Swordfish
1 hour ago
@Someprogrammerdude What do you expect to not happen? Objects are expected to not be destructed, now?
â curiousguy
1 hour ago
3
eel.is/c++draft/except.ctor#2 ??
â Swordfish
1 hour ago
3
"If an exception is thrown from a destructor of a local variable or of a temporary used in a return statement, the destructor for the object returned from the function is also invoked. (since C++14)" en.cppreference.com/w/cpp/language/throw
â Mat
1 hour ago
3
This is defect #2176. The fix may not have made it into 6.3.
â molbdnilo
1 hour ago
 |Â
show 2 more comments
2
Compiler and version? Doesn't happen with cl v19.16.26926
â Swordfish
1 hour ago
@Someprogrammerdude What do you expect to not happen? Objects are expected to not be destructed, now?
â curiousguy
1 hour ago
3
eel.is/c++draft/except.ctor#2 ??
â Swordfish
1 hour ago
3
"If an exception is thrown from a destructor of a local variable or of a temporary used in a return statement, the destructor for the object returned from the function is also invoked. (since C++14)" en.cppreference.com/w/cpp/language/throw
â Mat
1 hour ago
3
This is defect #2176. The fix may not have made it into 6.3.
â molbdnilo
1 hour ago
2
2
Compiler and version? Doesn't happen with cl v19.16.26926
â Swordfish
1 hour ago
Compiler and version? Doesn't happen with cl v19.16.26926
â Swordfish
1 hour ago
@Someprogrammerdude What do you expect to not happen? Objects are expected to not be destructed, now?
â curiousguy
1 hour ago
@Someprogrammerdude What do you expect to not happen? Objects are expected to not be destructed, now?
â curiousguy
1 hour ago
3
3
eel.is/c++draft/except.ctor#2 ??
â Swordfish
1 hour ago
eel.is/c++draft/except.ctor#2 ??
â Swordfish
1 hour ago
3
3
"If an exception is thrown from a destructor of a local variable or of a temporary used in a return statement, the destructor for the object returned from the function is also invoked. (since C++14)" en.cppreference.com/w/cpp/language/throw
â Mat
1 hour ago
"If an exception is thrown from a destructor of a local variable or of a temporary used in a return statement, the destructor for the object returned from the function is also invoked. (since C++14)" en.cppreference.com/w/cpp/language/throw
â Mat
1 hour ago
3
3
This is defect #2176. The fix may not have made it into 6.3.
â molbdnilo
1 hour ago
This is defect #2176. The fix may not have made it into 6.3.
â molbdnilo
1 hour ago
 |Â
show 2 more comments
1 Answer
1
active
oldest
votes
up vote
11
down vote
accepted
As per the standard this behavior is wrong and this has already been mentioned in the comments section of the question.
This is stated in the section on Exception handling.
As per the defect reports at open-std.org, they have been aware that implementations (GCC and Clang) were wrong about this as early as 2015-09-28.
But the proposed resolution was only in February, 2016 and the compilers (GCC and Clang) have not yet included this fix.
Proposed resolution (February, 2016):
Change 18.2 [except.ctor] paragraph 2 as follows:
The destructor is invoked for each automatic object of class type constructed, but not yet destroyed, since the try block was entered. If an exception is thrown during the destruction of temporaries or local variables for a return statement (9.6.3 [stmt.return]), the destructor for the returned object (if any) is also invoked. The objects are destroyed in the reverse order of the completion of their construction. [Example:struct A ;
struct Y ~Y() noexcept(false) throw 0; ;
A f()
try
A a;
Y y;
A b;
return ; // #1
catch (...)
return ; // #2
At #1, the returned object of type A is constructed. Then, the local variable b is destroyed (9.6 [stmt.jump]). Next, the local variable y is destroyed, causing stack unwinding, resulting in the destruction of the returned object, followed by the destruction of the local variable a. Finally, the returned object is constructed again at #2. âÂÂend example]
There have been bugs filed against this issue both in GCC and Clang.
The comments on the GCC bug report indicate that it is clearly a bug.
Jonathan Wakely comments:
It's now 2013 so the sensible thing to do is not return by value if your destructor can throw.
And another user:
Yes, I noticed, and Clang has also had a bug filed against them which has languished for years. Nevertheless, the behavior is wrong.
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
11
down vote
accepted
As per the standard this behavior is wrong and this has already been mentioned in the comments section of the question.
This is stated in the section on Exception handling.
As per the defect reports at open-std.org, they have been aware that implementations (GCC and Clang) were wrong about this as early as 2015-09-28.
But the proposed resolution was only in February, 2016 and the compilers (GCC and Clang) have not yet included this fix.
Proposed resolution (February, 2016):
Change 18.2 [except.ctor] paragraph 2 as follows:
The destructor is invoked for each automatic object of class type constructed, but not yet destroyed, since the try block was entered. If an exception is thrown during the destruction of temporaries or local variables for a return statement (9.6.3 [stmt.return]), the destructor for the returned object (if any) is also invoked. The objects are destroyed in the reverse order of the completion of their construction. [Example:struct A ;
struct Y ~Y() noexcept(false) throw 0; ;
A f()
try
A a;
Y y;
A b;
return ; // #1
catch (...)
return ; // #2
At #1, the returned object of type A is constructed. Then, the local variable b is destroyed (9.6 [stmt.jump]). Next, the local variable y is destroyed, causing stack unwinding, resulting in the destruction of the returned object, followed by the destruction of the local variable a. Finally, the returned object is constructed again at #2. âÂÂend example]
There have been bugs filed against this issue both in GCC and Clang.
The comments on the GCC bug report indicate that it is clearly a bug.
Jonathan Wakely comments:
It's now 2013 so the sensible thing to do is not return by value if your destructor can throw.
And another user:
Yes, I noticed, and Clang has also had a bug filed against them which has languished for years. Nevertheless, the behavior is wrong.
add a comment |Â
up vote
11
down vote
accepted
As per the standard this behavior is wrong and this has already been mentioned in the comments section of the question.
This is stated in the section on Exception handling.
As per the defect reports at open-std.org, they have been aware that implementations (GCC and Clang) were wrong about this as early as 2015-09-28.
But the proposed resolution was only in February, 2016 and the compilers (GCC and Clang) have not yet included this fix.
Proposed resolution (February, 2016):
Change 18.2 [except.ctor] paragraph 2 as follows:
The destructor is invoked for each automatic object of class type constructed, but not yet destroyed, since the try block was entered. If an exception is thrown during the destruction of temporaries or local variables for a return statement (9.6.3 [stmt.return]), the destructor for the returned object (if any) is also invoked. The objects are destroyed in the reverse order of the completion of their construction. [Example:struct A ;
struct Y ~Y() noexcept(false) throw 0; ;
A f()
try
A a;
Y y;
A b;
return ; // #1
catch (...)
return ; // #2
At #1, the returned object of type A is constructed. Then, the local variable b is destroyed (9.6 [stmt.jump]). Next, the local variable y is destroyed, causing stack unwinding, resulting in the destruction of the returned object, followed by the destruction of the local variable a. Finally, the returned object is constructed again at #2. âÂÂend example]
There have been bugs filed against this issue both in GCC and Clang.
The comments on the GCC bug report indicate that it is clearly a bug.
Jonathan Wakely comments:
It's now 2013 so the sensible thing to do is not return by value if your destructor can throw.
And another user:
Yes, I noticed, and Clang has also had a bug filed against them which has languished for years. Nevertheless, the behavior is wrong.
add a comment |Â
up vote
11
down vote
accepted
up vote
11
down vote
accepted
As per the standard this behavior is wrong and this has already been mentioned in the comments section of the question.
This is stated in the section on Exception handling.
As per the defect reports at open-std.org, they have been aware that implementations (GCC and Clang) were wrong about this as early as 2015-09-28.
But the proposed resolution was only in February, 2016 and the compilers (GCC and Clang) have not yet included this fix.
Proposed resolution (February, 2016):
Change 18.2 [except.ctor] paragraph 2 as follows:
The destructor is invoked for each automatic object of class type constructed, but not yet destroyed, since the try block was entered. If an exception is thrown during the destruction of temporaries or local variables for a return statement (9.6.3 [stmt.return]), the destructor for the returned object (if any) is also invoked. The objects are destroyed in the reverse order of the completion of their construction. [Example:struct A ;
struct Y ~Y() noexcept(false) throw 0; ;
A f()
try
A a;
Y y;
A b;
return ; // #1
catch (...)
return ; // #2
At #1, the returned object of type A is constructed. Then, the local variable b is destroyed (9.6 [stmt.jump]). Next, the local variable y is destroyed, causing stack unwinding, resulting in the destruction of the returned object, followed by the destruction of the local variable a. Finally, the returned object is constructed again at #2. âÂÂend example]
There have been bugs filed against this issue both in GCC and Clang.
The comments on the GCC bug report indicate that it is clearly a bug.
Jonathan Wakely comments:
It's now 2013 so the sensible thing to do is not return by value if your destructor can throw.
And another user:
Yes, I noticed, and Clang has also had a bug filed against them which has languished for years. Nevertheless, the behavior is wrong.
As per the standard this behavior is wrong and this has already been mentioned in the comments section of the question.
This is stated in the section on Exception handling.
As per the defect reports at open-std.org, they have been aware that implementations (GCC and Clang) were wrong about this as early as 2015-09-28.
But the proposed resolution was only in February, 2016 and the compilers (GCC and Clang) have not yet included this fix.
Proposed resolution (February, 2016):
Change 18.2 [except.ctor] paragraph 2 as follows:
The destructor is invoked for each automatic object of class type constructed, but not yet destroyed, since the try block was entered. If an exception is thrown during the destruction of temporaries or local variables for a return statement (9.6.3 [stmt.return]), the destructor for the returned object (if any) is also invoked. The objects are destroyed in the reverse order of the completion of their construction. [Example:struct A ;
struct Y ~Y() noexcept(false) throw 0; ;
A f()
try
A a;
Y y;
A b;
return ; // #1
catch (...)
return ; // #2
At #1, the returned object of type A is constructed. Then, the local variable b is destroyed (9.6 [stmt.jump]). Next, the local variable y is destroyed, causing stack unwinding, resulting in the destruction of the returned object, followed by the destruction of the local variable a. Finally, the returned object is constructed again at #2. âÂÂend example]
There have been bugs filed against this issue both in GCC and Clang.
The comments on the GCC bug report indicate that it is clearly a bug.
Jonathan Wakely comments:
It's now 2013 so the sensible thing to do is not return by value if your destructor can throw.
And another user:
Yes, I noticed, and Clang has also had a bug filed against them which has languished for years. Nevertheless, the behavior is wrong.
edited 25 mins ago
answered 53 mins ago
P.W
6,5441336
6,5441336
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53167490%2fdestruction-of-return-value-on-destructor-exception%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password

2
Compiler and version? Doesn't happen with cl v19.16.26926
â Swordfish
1 hour ago
@Someprogrammerdude What do you expect to not happen? Objects are expected to not be destructed, now?
â curiousguy
1 hour ago
3
eel.is/c++draft/except.ctor#2 ??
â Swordfish
1 hour ago
3
"If an exception is thrown from a destructor of a local variable or of a temporary used in a return statement, the destructor for the object returned from the function is also invoked. (since C++14)" en.cppreference.com/w/cpp/language/throw
â Mat
1 hour ago
3
This is defect #2176. The fix may not have made it into 6.3.
â molbdnilo
1 hour ago