Skip to content

Instantly share code, notes, and snippets.

@muzhig
Forked from anonymous/gist:4509917
Created January 11, 2013 11:12
Show Gist options
  • Save muzhig/4509922 to your computer and use it in GitHub Desktop.
Save muzhig/4509922 to your computer and use it in GitHub Desktop.
class backtrace
{
boost::shared_array<void*> m_backtrace;
size_t m_trace_size;
public:
static const int DEFAULT_STACK_DEPTH = 100;
static const int DEFAULT_EXCLUDE_FIRST_FRAMES_COUNT = 1;
typedef std::vector<std::string> stack_type;
/// Collect N back traces, exclude first E frames
backtrace(int depth = DEFAULT_STACK_DEPTH, int exclude_cnt = DEFAULT_EXCLUDE_FIRST_FRAMES_COUNT)
{
void* bt[depth];
size_t size = ::backtrace(bt, depth);
if (size > size_t(exclude_cnt))
{
m_trace_size = size - exclude_cnt;
m_backtrace = boost::shared_array<void*>(new void*[m_trace_size]);
std::copy(bt + exclude_cnt, bt + size, m_backtrace.get());
}
}
stack_type stack() const
{
stack_type result;
if (m_trace_size > 0)
{
if (char** strings = backtrace_symbols(m_backtrace.get(), m_trace_size))
{
for (size_t i = 0; i < m_trace_size; ++i)
{
// Try to demangle current name
if (char* open_bracket = strrchr(strings[i], '('))
{
if (char* plus_sign = strchr(open_bracket, '+'))
{
*plus_sign = 0;
int status;
char* n = abi::__cxa_demangle(++open_bracket, 0, 0, &status);
*plus_sign = '+';
if (!status)
{
std::string r(strings[i], open_bracket - strings[i]);
r += n + std::string(plus_sign);
result.push_back(r);
free(n);
continue;
}
}
}
result.push_back(strings[i]);
}
free(strings);
}
}
return result;
}
};
inline std::ostream& operator<<(std::ostream& os, const backtrace& bt)
{
backtrace::stack_type stack = bt.stack();
std::copy(stack.begin(), stack.end(), std::ostream_iterator<std::string>(os, "\n"));
return os;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment