Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
181 views
in Technique[技术] by (71.8m points)

c++ - Exception slicing - is this due to generated copy constructor?

I've just fixed a very subtle bug in our code, caused by slicing of an exception, and I now want to make sure I understand exactly what was happening.

Here's our base exception class, a derived class, and relevant functions:

class Exception
{
public:
  // construction
  Exception(int code, const char* format="", ...);
  virtual ~Exception(void);

  <snip - get/set routines and print function>

protected:
private:
  int mCode;                // thrower sets this
  char mMessage[Exception::MessageLen]; // thrower says this FIXME: use String
};

class Derived : public Exception {
public:
  Derived (const char* throwerSays) : Exception(1, throwerSays) {};
};

void innercall {
  <do stuff>
  throw Derived("Bad things happened!");
}

void outercall {
  try {
    innercall();
  }
  catch(Exception& e)
  {
    printf("Exception seen here! %s %d
", __FILE__, __LINE__);
    throw e;
  }
}

The bug was of course that outercall ends up throwing an Exception, instead of a Derived. My bug resulted from higher in the call stack attempts to catch the Derived failing.

Now, I just want to make sure I understand - I believe that at the 'throw e' line, a new Exception object is being created, using a default copy constructor. Is that what's really going on?

If so, am I allowed to lock out copy constructors for objects that will be thrown? I'd really prefer this not happen again, and our code has no reason to copy Exception objects (that I know of).

Please, no comments on the fact that we have our own exception hierarchy. That's a bit of old design that I'm working to correct (I'm making good progress. I've gotten rid of the home-grown string class, and many of the home-grown containers.)

UPDATE: To be clear, I had fixed the bug (by changing 'throw e' to 'throw') before I ever asked the question. I was just looking for confirmation of what was going on.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

When you throw an object, you're actually throwing a copy of the object, not the original. Think about it - the original object is on the stack, but the stack is being unwound and invalidated.

I believe this is part of the standard, but I don't have a copy to reference.

The type of exception being thrown in the catch block is the base type of the catch, not the type of the object that was thrown. The way around this problem is to throw; rather than throw e; which will throw the original caught exception.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...