By Aditya Ishan


2019-03-12 09:37:35 8 Comments

Why does the outer temp become empty after catching first exception?

#include <iostream>
int main()
{
    std::string temp("exception");
    int value;
    while(std::cin>> value && value != 0)
    {
         try{
              if(value > 9) throw temp;
              else std::cout << value << "\n";
            }
         catch(std::string temp)
         {
              std::cout << temp << "\n";
         }
    }

    return 0;
}

Input:

1
2
11
13

Output:

1
2
exception
// Printing Empty string

Expected Output:

1
2
exception
exception

I compile my code with g++ 7.3.0.

2 comments

@Manoj 2019-03-12 10:08:40

I am not sure if it is a bug or not as mentioned in another answer but somehow catch block is changing / omitting the content of temp after handling the exception once. Below code resolves this issue. Make the temp a const to solve this.

#include <iostream>
    int main()
    {
        const std::string temp("exception");
        int value;
        while(std::cin>> value && value != 0)
        {
             try{
                  if(value > 9) throw temp;
                  else std::cout << value << "\n";
                }
             catch(std::string temp){
                  std::cerr << temp << "\n";
                  }
        }

        return 0;
    }

@Christian Severin 2019-03-12 13:06:40

An hour before you wrote your answer, this solution was mentioned both in a comment and in the answer by @StoryTeller.

@Manoj 2019-03-13 07:57:05

Believe it or not, I didn't really see those comments and had started playing with this code and as soon as it worked I posted my answer. Taking it as a lesson to read all the comments before posting my answers. Thanks for the down votes.

@StoryTeller 2019-03-12 09:51:29

This appears to be a bug in GCC's implementation of copy elision. The C++ standard says the following:

[class.copy.elision] (emphasis mine)

This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies):

  • in a throw-expression, when the operand is the name of a non-volatile automatic object (other than a function or catch-clause parameter) whose scope does not extend beyond the end of the innermost enclosing try-block (if there is one), the copy/move operation from the operand to the exception object can be omitted by constructing the automatic object directly into the exception object

In the following copy-initialization contexts, a move operation might be used instead of a copy operation:

  • if the operand of a throw-expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) whose scope does not extend beyond the end of the innermost enclosing try-block (if there is one),

This is a family of optimizations that allows the copy initialization of an exception object to be either avoided or done as efficiently as possible. Now, a common implementation of std::string move construction is to leave the source string empty. This appears to be exactly what happens to your code. The temp in the outer scope is moved from (and left empty).

But that is not the intended behavior. The scope of the temp you throw exceeds (by far) the try block it's thrown in. So GCC has no business applying copy elision to it.

A possible workaround is to place the declaration of temp inside the while loop. This initialized a new std::string object every iteration, so even if GCC moves from it, it won't be noticeable.

Another workaround was mentioned in the comments and is to make the outer temp a const object. This will force a copy (since a move operation requires a non-const source object).

Related Questions

Sponsored Content

16 Answered Questions

[SOLVED] Why should I not wrap every block in "try"-"catch"?

1 Answered Questions

10 Answered Questions

[SOLVED] Do try/catch blocks hurt performance when exceptions are not thrown?

4 Answered Questions

[SOLVED] Method return statement vs try-catch

1 Answered Questions

Confused about calling on methods containing 'try-catch' blocks

5 Answered Questions

[SOLVED] Try-catch speeding up my code?

4 Answered Questions

[SOLVED] Using try-catch with a if else loop

2 Answered Questions

[SOLVED] Not allowed try catch block for basic input computation

  • 2015-06-21 16:25:40
  • Christopher Dudley
  • 70 View
  • 0 Score
  • 2 Answer
  • Tags:   java try-catch

0 Answered Questions

Using Command Line input CTRL+D with try catch statements

  • 2014-05-12 00:59:38
  • user3613892
  • 623 View
  • 0 Score
  • 0 Answer
  • Tags:   java try-catch

3 Answered Questions

[SOLVED] Java: Why does try-catch block within a loop executes only once?

Sponsored Content