For a More Java-Like Structure

The one difference between the stacktrace produced from the method used by ELF and the one in Java is that, in the case of ELF, a method's signature only appears in the stacktrace if the exception happened to have propagated through that method. In the case of Java, the exception will readily contain the complete stacktrace, starting from main() (or Thread.run()), the moment it is instantiated.

It is possible to adapt ELF to mimic the exact Java behavior if run-time efficiency is sacrificed a little. Two methods for providing a more Java-like stacktrace are as follows.

In the first variation, modify the definition of ELF_FUNCT_DEF() to remove the try/catch clause. Instead, of using a try/catch clause, instantiate a guard-like object based on Stroustrup's "resource acquisition is initialization" strategy [3]. This object's constructor will push() the current method's signature to a std::stack<std::string> object that is attached to the current thread using Thread-specific data [1]. Similarly, its destructor will pop() the signature from the stack. At any point in time, one can examine this stack object attached to the thread in order to retrieve the complete method invocation stack trace. The main drawback of this method is the increased overhead associated with each method invocation, irrespective of whether an exception is thrown.

In the second variation, to avoid the expensive TSD, use a Singleton object of type map<pthread_t, stack>. The ELF_FUNCT_DEF() expands to include the code to access this Singleton object, on a method invocation, and to push() its signature to the associated stack object. The problem with this method is the fact that C++ STL containers are not thread safe when accessed simultaneously from multiple threads. To overcome this problem, the Singleton object will have to be protected using locks (mutexes), which slows down the method invocations due to the serializing effect.

The method described in my article does not suffer from any of these drawbacks. The extra code is executed only when an exception is thrown. Moreover, in most cases, stacktrace is only useful from the point of origin (where it was thrown) to the point where it is caught and logged.

— S.A.

Back to Article