Destruction of return value on destructor exception

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
25
down vote

favorite
2












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










share|improve this question



















  • 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














up vote
25
down vote

favorite
2












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










share|improve this question



















  • 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












up vote
25
down vote

favorite
2









up vote
25
down vote

favorite
2






2





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










share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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












  • 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












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.







share|improve this answer






















    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













     

    draft saved


    draft discarded


















    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






























    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.







    share|improve this answer


























      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.







      share|improve this answer
























        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.







        share|improve this answer














        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.








        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 25 mins ago

























        answered 53 mins ago









        P.W

        6,5441336




        6,5441336



























             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            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













































































            Comments

            Popular posts from this blog

            White Anglo-Saxon Protestant

            Is the Concept of Multiple Fantasy Races Scientifically Flawed? [closed]

            One-line joke