1. Roger Pate
  2. nonsense

Commits

Roger Pate  committed 7d4b500

Add backtrace(3) sample.

  • Participants
  • Parent commits f4e9475
  • Branches default

Comments (0)

Files changed (3)

File .hgignore

View file
 *.so
 *.pyo
 *.pyc
-ld-rpath/main
+
+syntax: regexp
+^build/
+^ld-rpath/main

File Makefile

View file
+BIN := build/backtrace
+
+.PHONY: all
+all: $(BIN)
+
+.PHONY: clean
+clean:
+	-rm -r build
+
+build:
+	mkdir $@
+
+build/backtrace: backtrace.cpp | build
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -rdynamic $< -o $@

File backtrace.cpp

View file
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <iostream>
+#include <iterator>
+#include <stdexcept>
+#include <string>
+#include <vector>
+
+#include <execinfo.h>
+
+
+struct Backtrace {
+  explicit Backtrace(int size=100, int ignore=0) : _buffer (size) {
+    assert(ignore >= 0);
+    _ignored = ignore + 1;  // Ignore this ctor too.
+    while (true) {
+      int r = backtrace(&_buffer[0], _buffer.size());
+      if (r < _buffer.size()) {
+        _buffer.resize(r);
+        break;
+      }
+      _buffer.resize(_buffer.size() * 2 + 3);  // Nearly-baseless heuristic.
+    }
+  }
+
+  void ignore(int num) {
+    assert(num >= 0);
+    _ignored += num;
+  }
+
+  void print(std::ostream &s) const {
+    strings(std::ostream_iterator<char const*>(s, "\n"));
+    s.flush();
+  }
+
+  void print(int fd) const {
+    if (_ignored < _buffer.size()) {
+      backtrace_symbols_fd(&_buffer[_ignored], _buffer.size() - _ignored, fd);
+    }
+  }
+
+  template<class OutIter>
+  void strings(OutIter out) const {
+    if (_ignored >= _buffer.size()) return;
+    char **symbols = backtrace_symbols(&_buffer[_ignored], _buffer.size() - _ignored);
+    if (!symbols) {
+      throw std::runtime_error(std::string("backtrace_symbols: ") + strerror(errno));
+    }
+    try {
+      typedef char const *const *S;
+      S begin = symbols,
+        end = symbols + (_buffer.size() - _ignored);
+      for (; begin != end; ++begin) {
+        *out = *begin;
+        ++out;
+      }
+    }
+    catch (...) {
+      free(symbols);
+      throw;
+    }
+    free(symbols);
+  }
+
+private:
+  std::vector<void*> _buffer;
+  int _ignored;
+};
+
+void show_backtrace_example() {
+  Backtrace bt;
+  bt.ignore(1);  // Ignore this function.
+  bt.print(std::cout);
+  std::cout << '\n';
+  bt.print(1);
+}
+
+void f() { show_backtrace_example(); }
+void g() { f(); }
+
+int main() {
+  g();
+  return 0;
+}