diff --git a/components/common/cpp/include/ftl/exception.hpp b/components/common/cpp/include/ftl/exception.hpp
index 07f7a366adf65cb7baea83624d8f1ff53a3cf848..43e303d9b803282408bea3096d1503b45597d031 100644
--- a/components/common/cpp/include/ftl/exception.hpp
+++ b/components/common/cpp/include/ftl/exception.hpp
@@ -7,29 +7,29 @@ namespace ftl {
 class Formatter {
 	public:
 	Formatter() {}
-    ~Formatter() {}
+	~Formatter() {}
 
-    template <typename Type>
-    inline Formatter & operator << (const Type & value)
-    {
-        stream_ << value;
-        return *this;
-    }
+	template <typename Type>
+	inline Formatter & operator << (const Type & value)
+	{
+		stream_ << value;
+		return *this;
+	}
 
-    inline std::string str() const         { return stream_.str(); }
-    inline operator std::string () const   { return stream_.str(); }
+	inline std::string str() const         { return stream_.str(); }
+	inline operator std::string () const   { return stream_.str(); }
 
-    enum ConvertToString 
-    {
-        to_str
-    };
-    inline std::string operator >> (ConvertToString) { return stream_.str(); }
+	enum ConvertToString
+	{
+		to_str
+	};
+	inline std::string operator >> (ConvertToString) { return stream_.str(); }
 
 private:
-    std::stringstream stream_;
+	std::stringstream stream_;
 
-    Formatter(const Formatter &);
-    Formatter & operator = (Formatter &);
+	Formatter(const Formatter &);
+	Formatter & operator = (Formatter &);
 };
 
 class exception : public std::exception
@@ -39,22 +39,30 @@ class exception : public std::exception
 	explicit exception(const Formatter &msg);
 	~exception();
 
-	const char * what () const throw () {
+	const char* what() const throw () {
 		processed_ = true;
-    	return msg_.c_str();
-    }
+		return msg_.c_str();
+	}
 
-    const char * trace () const throw () {
-        return trace_.c_str();
-    }
+	std::string trace() const throw () {
+		return decode_backtrace();
+	}
 
 	void ignore() const { processed_ = true; }
 
 	private:
+	std::string decode_backtrace() const;
+
 	std::string msg_;
-    std::string trace_;
 	mutable bool processed_;
+
+#ifdef __GNUC__
+	static const int TRACE_SIZE_MAX_ = 16;
+	void* trace_[TRACE_SIZE_MAX_];
+	int trace_size_;
+#endif
 };
+
 }
 
 #define FTL_Error(A) (ftl::exception(ftl::Formatter() << __FILE__ << ":" << __LINE__ << ": " << A))
diff --git a/components/common/cpp/src/exception.cpp b/components/common/cpp/src/exception.cpp
index 46897adea1ef16ffa739a8fda961fd9d5fc6f70f..19edc276e8db8fd3dc2888bdec1a98e2b189f6e2 100644
--- a/components/common/cpp/src/exception.cpp
+++ b/components/common/cpp/src/exception.cpp
@@ -7,53 +7,52 @@
 #include <execinfo.h>
 #include <dlfcn.h>
 #include <cxxabi.h>
-#endif
-
-using ftl::exception;
-using std::string;
 
-static std::string demangle(const char* name) {
+std::string demangle(const char* name) {
 	if (!name) {
 		return "[unknown symbol]";
 	}
-#ifdef __GNUC__
 	int status;
 	char* demangled = abi::__cxa_demangle(name, NULL, 0, &status);
 	if (!demangled) {
 		return std::string(name);
 	}
 	else {
-		auto result = string(demangled);
+		auto result = std::string(demangled);
 		free(demangled);
 		return result;
 	}
-#else
-	return std::string(name);
-#endif
 }
 
-static std::string addr_to_string(const void* addr) {
+#endif
+
+using ftl::exception;
+using std::string;
+
+string addr_to_string(const void* addr) {
 	std::stringstream ss;
 	ss << addr;
 	return ss.str();
 }
 
-static std::string getBackTrace() {
 #ifdef __GNUC__
+string exception::decode_backtrace() const {
 	string result;
-	void *trace[16];
-	int trace_size = 0;
-	trace_size = backtrace(trace, 16);
-	char **messages = backtrace_symbols(trace, trace_size);
+	// backtrace_symbols() as fallback (no data from dladdr())
+	char **messages = backtrace_symbols(trace_, trace_size_);
 
-	result = "[bt] Trace:\n";
+	if (!messages) {
+		return string("[bt] no trace");
+	}
 
 	/* skip first stack frame (points here) */
-	for (int i=2; i < trace_size; ++i) {
-		result += string("[bt] #") + std::to_string(i-1) + string(" ");
+	for (int i=1; i < trace_size_; ++i) {
+		result += string("[bt] #") + std::to_string(i-1)
+				+ string(TRACE_SIZE_MAX_/10 - (i-1)/10, ' ')
+				+ string(" ");
 
 		Dl_info info;
-		if (dladdr(trace[i], &info) && info.dli_saddr) {
+		if (dladdr(trace_[i], &info) && info.dli_saddr) {
 			auto name = demangle(info.dli_sname);
 			string fname = info.dli_fname ? info.dli_fname: "[unknown file]";
 
@@ -71,25 +70,31 @@ static std::string getBackTrace() {
 
 	free(messages);
 	return result;
+}
 
-#elif _MSC_VER
-	return "";
 #else
-	return "";
-#endif
+string exception::decode_backtrace() const {
+	return string();
 }
+#endif
 
 exception::exception(const char *msg) : msg_(msg), processed_(false) {
-	trace_ = std::move(getBackTrace());
+	#ifdef __GNUC__
+	trace_size_ = backtrace(trace_, TRACE_SIZE_MAX_);
+	#endif
 }
 
 exception::exception(const ftl::Formatter &msg) : msg_(msg.str()), processed_(false) {
-	trace_ = std::move(getBackTrace());
+	#ifdef __GNUC__
+	trace_size_ = backtrace(trace_, TRACE_SIZE_MAX_);
+	#endif
 }
 
 exception::~exception() {
 	if (!processed_) {
 		LOG(ERROR) << "Unhandled exception: " << what();
-		LOG(ERROR) << trace_;
+		#ifdef __GNUC__
+		LOG(ERROR) << "Trace:\n" << decode_backtrace();
+		#endif
 	}
 }