clear explanation sought: throw() and stack unwinding

Posted by Jerry Gagelman on Programmers See other posts from Programmers or by Jerry Gagelman
Published on 2011-03-10T23:32:02Z Indexed on 2011/03/11 0:18 UTC
Read the original article Hit count: 471

Filed under:

I'm not a programmer but have learned a lot watching others. I am writing wrapper classes to simplify things with a really technical API that I'm working with. Its routines return error codes, and I have a function that converts those to strings:

static const char* LibErrString(int errno);

For uniformity I decided to have member of my classes throw an exception when an error is encountered. I created a class:

struct MyExcept : public std::exception {
   const char* errstr_;
   const char* what() const throw() {return errstr_;}
   MyExcept(const char* errstr) : errstr_(errstr) {}
};

Then, in one of my classes:

class Foo {
public:
   void bar() {
   int err = SomeAPIRoutine(...);
   if (err != SUCCESS) throw MyExcept(LibErrString(err));
   // otherwise...
   }
};

The whole thing works perfectly: if SomeAPIRoutine returns an error, a try-catch block around the call to Foo::bar catches a standard exception with the correct error string in what().

Then I wanted the member to give more information:

void Foo::bar() {
   char adieu[128];
   int err = SomeAPIRoutine(...);
   if (err != SUCCESS) {
      std::strcpy(adieu,"In Foo::bar... ");
      std::strcat(adieu,LibErrString(err));
      throw MyExcept((const char*)adieu);
   }
   // otherwise...
}

However, when SomeAPIRoutine returns an error, the what() string returned by the exception contains only garbage. It occurred to me that the problem could be due to adieu going out of scope once the throw is called. I changed the code by moving adieu out of the member definition and making it an attribute of the class Foo. After this, the whole thing worked perfectly: a try-call block around a call to Foo::bar that catches an exception has the correct (expanded) string in what().

Finally, my question: what exactly is popped off the stack (in sequence) when the exception is thrown in the if-block when the stack "unwinds?" As I mentioned above, I'm a mathematician, not a programmer. I could use a really lucid explanation of what goes onto the stack (in sequence) when this C++ gets converted into running machine code.

© Programmers or respective owner

Related posts about c++