eljefedelrodeodeljefe
eljefedelrodeodeljefe

Reputation: 6791

How to observe improper stack unwinding?

We have some c++ code that can make calls to exit(3) through the users API. My assumption is that we are not properly unwinding stacks and that this considered bad in c++. Also there is a big c++ library involved that must be considered a black box.

I want to patch this, and also have an idea how, but don't know how to observe and compare the change. Can I make this somehow visible? Possibly on OS X?

Upvotes: 0

Views: 112

Answers (1)

davidbak
davidbak

Reputation: 5999

exit() apparently does some cleanup. This is described in section 18.5 [support.start.term] of the standard, but the frequently correct site www.cplusplus.com summarizes it.

So it says objects with static storage or thread storage will be cleaned up, as will the entire I/O system (files will be flushed, etc).

But there are other ways to exit without running the C++ cleanup. For example, if it is a library that calls exit and it is a C language library (not C++) then it may or may not do the C++ cleanup. Or there are calls to abort or quick_exit. And, too, if you call the OS directly (e.g., ExitProcess() on Windows) then the process exits immediately and no C++ cleanup is done.

If you want to make the behavior visible: Make a object with a destructor that does something interesting - like log a message somewhere. Or maybe when it is constructed it creates a file with a certain name and when destructed it deletes it. Declare an instance this object in your main(). Declare another one (with a different message) at static scope. So now you have an effect observable in your environment.

The following is from 18.5 of N4140 (2014-10-07):

[[noreturn]] void exit(int status) 
8 The function exit() has additional behavior in this International Standard:
(8.1) First, objects with thread storage duration and associated with the current
      thread are destroyed. Next,objects with static storage duration are destroyed
      and functions registered by calling `atexit` are called. See 3.6.3 for the
      order of destructions and calls. (Automatic objects are not destroyed as a
      result of calling `exit()`.) If control leaves a registered function called by
      `exit` because the function does not provide a handler for a thrown exception,
      `std::terminate()` shall be called (15.5.1).
(8.2) Next, all open C streams (as mediated by the function signatures declared in
      `<cstdio>`) with unwritten buffered data are flushed, all open C streams are
      closed, and all files created by calling `tmpfile()` are removed.
(8.3) Finally, control is returned to the host environment. If `status` is zero or
      `EXIT_SUCCESS`, an implementation-defined form of the status _successful 
      termination_ is returned. If `status` is `EXIT_FAILURE`, an implementation-
      defined form of the status _unsuccessful termination_ is returned. Otherwise 
      the status returned is implementation-defined.

Upvotes: 1

Related Questions