Some CI and cmake changes (#9)

This commit is contained in:
Jeremy Rifkin 2023-07-18 22:21:56 -04:00 committed by GitHub
parent f28c2cac3a
commit 04f8b88efd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 198 additions and 120 deletions

6
.clang-tidy Normal file
View File

@ -0,0 +1,6 @@
---
Checks: '-*,clang-diagnostic-*,clang-analyzer-*,bugprone-*,cert-*,clang-analyzer-*,concurrency-*,cppcoreguidelines-*,misc-*,modernize-*,performance-*,portability-*,readability-*,-cppcoreguidelines-macro-usage,-modernize-use-trailing-return-type,-misc-non-private-member-variables-in-classes,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-type-vararg,-cppcoreguidelines-avoid-c-arrays,-modernize-avoid-c-arrays,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-readability-else-after-return,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cert-dcl50-cpp,-cppcoreguidelines-init-variables,-readability-implicit-bool-conversion,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-owning-memory,-cppcoreguidelines-pro-type-member-init,-readability-isolate-declaration,-cppcoreguidelines-avoid-magic-numbers,-readability-magic-numbers,-cppcoreguidelines-pro-type-union-access,-cppcoreguidelines-pro-type-cstyle-cast,-readability-named-parameter,-cppcoreguidelines-avoid-goto,-readability-uppercase-literal-suffix,-performance-avoid-endl,-bugprone-easily-swappable-parameters'
WarningsAsErrors: '*'
HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false
FormatStyle: none

View File

@ -43,7 +43,7 @@ jobs:
-D${{matrix.symbols}}=On \
-D${{matrix.demangle}}=On \
-DCPPTRACE_BACKTRACE_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/include/backtrace.h
make
make -j
build-macos:
runs-on: macos-13
strategy:
@ -79,7 +79,7 @@ jobs:
-D${{matrix.unwind}}=On \
-D${{matrix.symbols}}=On \
-D${{matrix.demangle}}=On
make
make -j
build-windows:
runs-on: windows-2019
strategy:
@ -143,7 +143,7 @@ jobs:
-DCMAKE_CXX_STANDARD=${{matrix.std}} \
-DCPPTRACE_BACKTRACE_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/include/backtrace.h \
${{matrix.config}}
make
make -j
build-macos-full-or-auto:
runs-on: macos-13
strategy:
@ -164,7 +164,7 @@ jobs:
-DCMAKE_CXX_COMPILER=${{matrix.compiler}} \
-DCMAKE_CXX_STANDARD=${{matrix.std}} \
${{matrix.config}}
make
make -j
# TODO: -DCMAKE_CXX_STANDARD isn't being honored?
# build-linux-full-or-auto-23:
# runs-on: ubuntu-22.04

18
.github/workflows/lint.yml vendored Normal file
View File

@ -0,0 +1,18 @@
name: lint
on:
push:
pull_request:
jobs:
lint:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: dependencies
run: |
sudo apt install clang-tidy
- name: clang-tidy
run: |
chmod +x lint.sh
./lint.sh -DCPPTRACE_BACKTRACE_PATH=\"/usr/lib/gcc/x86_64-linux-gnu/10/include/backtrace.h\"

View File

@ -37,7 +37,7 @@ jobs:
-DCPPTRACE_BACKTRACE_PATH=/usr/lib/gcc/x86_64-linux-gnu/11/include/backtrace.h \
-DCPPTRACE_BUILD_SPEEDTEST=On \
-DBUILD_SHARED_LIBS=On
make
make -j
- name: test
working-directory: build
run: |

View File

@ -48,7 +48,7 @@ jobs:
-DCPPTRACE_BUILD_TEST=On \
$(if [ "${{matrix.symbols}}" = "CPPTRACE_GET_SYMBOLS_WITH_LIBDL" ]; then echo "-DCPPTRACE_BUILD_TEST_RDYNAMIC=On"; else echo ""; fi) \
-DBUILD_SHARED_LIBS=On
make
make -j
- name: test
working-directory: build
run: |
@ -91,7 +91,7 @@ jobs:
-DCPPTRACE_BUILD_TEST=On \
$(if [ "${{matrix.symbols}}" = "CPPTRACE_GET_SYMBOLS_WITH_LIBDL" ]; then echo "-DCPPTRACE_BUILD_TEST_RDYNAMIC=On"; else echo ""; fi) \
-DBUILD_SHARED_LIBS=On
make
make -j
- name: test
working-directory: build
run: |
@ -168,7 +168,7 @@ jobs:
${{matrix.config}} \
-DCPPTRACE_BUILD_TEST=On \
-DBUILD_SHARED_LIBS=On
make
make -j
- name: test
working-directory: build
run: |
@ -195,7 +195,7 @@ jobs:
${{matrix.config}} \
-DCPPTRACE_BUILD_TEST=On \
-DBUILD_SHARED_LIBS=On
make
make -j
- name: test
working-directory: build
run: |

6
.gitignore vendored
View File

@ -1,6 +1,4 @@
.vscode
build
build2
a.out
test/build
repro*/
build*
repro*

View File

@ -6,7 +6,7 @@ endif()
project(
cpptrace
VERSION 1.0.0
VERSION 0.0.1
LANGUAGES CXX
)
@ -28,6 +28,7 @@ target_include_directories(
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/cpptrace/cpptrace>
)
# TODO
target_compile_features(
cpptrace
PUBLIC
@ -44,7 +45,8 @@ set_target_properties(
target_compile_options(
cpptrace
PRIVATE
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall -Wextra -Werror=return-type -Wshadow>
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall -Wextra -Werror=return-type -Wshadow -Wundef>
$<$<CXX_COMPILER_ID:GNU>:-Wuseless-cast -Wnonnull-compare>
$<$<CXX_COMPILER_ID:MSVC>:/W4 /WX /permissive->
)

View File

@ -1,7 +1,6 @@
#ifndef CPPTRACE_HPP
#define CPPTRACE_HPP
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>

14
lint.sh Normal file
View File

@ -0,0 +1,14 @@
#!/bin/bash
status=0
while read f
do
echo checking $f
flags="-DCPPTRACE_FULL_TRACE_WITH_LIBBACKTRACE -DCPPTRACE_FULL_TRACE_WITH_STACKTRACE -DCPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE -DCPPTRACE_GET_SYMBOLS_WITH_LIBDL -DCPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE -DCPPTRACE_GET_SYMBOLS_WITH_NOTHING -DCPPTRACE_UNWIND_WITH_EXECINFO -DCPPTRACE_UNWIND_WITH_NOTHING -DCPPTRACE_DEMANGLE_WITH_CXXABI -DCPPTRACE_DEMANGLE_WITH_NOTHING"
clang-tidy $f -- -std=c++11 -Iinclude $@ $flags
ret=$?
if [ $ret -ne 0 ]; then
status=1
fi
done <<< $(find include src -name "*.hpp" -o -name "*.cpp" -not -path "test/speedtest.cpp" -not -path "src/full/full_trace_with_stacktrace.cpp")
exit $status

View File

@ -1,6 +1,7 @@
#include <cpptrace/cpptrace.hpp>
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>
#include <iostream>
@ -48,13 +49,13 @@ namespace cpptrace {
namespace cpptrace {
void print_trace(std::uint32_t skip) {
std::cerr<<"Stack trace (most recent call first):"<<std::endl;
std::size_t i = 0;
std::size_t counter = 0;
const auto trace = generate_trace(skip + 1);
// +1 to skip one frame
for(auto it = trace.begin() + 1; it != trace.end(); it++) {
const auto& frame = *it;
std::cerr
<< i++
<< counter++
<< " "
<< frame.filename
<< ":"

View File

@ -1,8 +1,6 @@
#ifndef CPPTRACE_DEMANGLE_HPP
#define CPPTRACE_DEMANGLE_HPP
#include <cpptrace/cpptrace.hpp>
#include <string>
namespace cpptrace {

View File

@ -1,6 +1,5 @@
#ifdef CPPTRACE_DEMANGLE_WITH_CXXABI
#include <cpptrace/cpptrace.hpp>
#include "cpptrace_demangle.hpp"
#include <cxxabi.h>
@ -14,9 +13,10 @@ namespace cpptrace {
int status;
char* demangled = abi::__cxa_demangle(name.c_str(), nullptr, nullptr, &status);
if(demangled) {
std::string s = demangled;
std::string str = demangled;
// NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
free(demangled);
return s;
return str;
} else {
return name;
}

View File

@ -1,9 +1,7 @@
#ifdef CPPTRACE_DEMANGLE_WITH_NOTHING
#include <cpptrace/cpptrace.hpp>
#include "cpptrace_demangle.hpp"
#include <cstdlib>
#include <string>
namespace cpptrace {

View File

@ -1,10 +1,11 @@
#ifdef CPPTRACE_FULL_TRACE_WITH_LIBBACKTRACE
#include <cpptrace/cpptrace.hpp>
#include "cpptrace_full_trace.hpp"
#include "../platform/cpptrace_program_name.hpp"
#include "../platform/cpptrace_common.hpp"
#include <cstddef>
#include <cstdint>
#include <vector>
#ifdef CPPTRACE_BACKTRACE_PATH
@ -16,7 +17,9 @@
namespace cpptrace {
namespace detail {
struct trace_data {
// NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members)
std::vector<stacktrace_frame>& frames;
// NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members)
size_t& skip;
};
@ -47,6 +50,7 @@ namespace cpptrace {
backtrace_state* get_backtrace_state() {
// backtrace_create_state must be called only one time per program
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
static backtrace_state* state = nullptr;
static bool called = false;
if(!called) {
@ -67,7 +71,7 @@ namespace cpptrace {
// fallback, try to at least recover the symbol name with backtrace_syminfo
backtrace_syminfo(
get_backtrace_state(),
reinterpret_cast<uintptr_t>(frame.address),
frame.address,
syminfo_callback,
error_callback,
&frame

View File

@ -13,16 +13,21 @@
#define CPPTRACE_MAYBE_UNUSED __attribute__((unused))
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <vector>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <ios>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
// Lightweight std::source_location.
struct source_location {
// NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members)
const char* const file;
//const char* const function; // disabled for now due to static constexpr restrictions
// NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members)
const int line;
constexpr source_location(
//const char* _function /*= __builtin_FUNCTION()*/,
@ -44,14 +49,20 @@ static void primitive_assert_impl(
const char* action = verify ? "verification" : "assertion";
const char* name = verify ? "verify" : "assert";
if(message == nullptr) {
fprintf(stderr, "Cpptrace %s failed at %s:%d: %s\n",
action, location.file, location.line, signature);
(void) fprintf(
stderr,
"Cpptrace %s failed at %s:%d: %s\n",
action, location.file, location.line, signature
);
} else {
fprintf(stderr, "Cpptrace %s failed at %s:%d: %s: %s\n",
action, location.file, location.line, signature, message);
(void) fprintf(
stderr,
"Cpptrace %s failed at %s:%d: %s: %s\n",
action, location.file, location.line, signature, message
);
}
fprintf(stderr, " primitive_%s(%s);\n", name, expression);
abort();
(void) fprintf(stderr, " primitive_%s(%s);\n", name, expression);
std::abort();
}
}
@ -70,15 +81,15 @@ void nothing() {}
#endif
CPPTRACE_MAYBE_UNUSED
static std::vector<std::string> split(const std::string& s, const std::string& delims) {
static std::vector<std::string> split(const std::string& str, const std::string& delims) {
std::vector<std::string> vec;
size_t old_pos = 0;
size_t pos = 0;
while((pos = s.find_first_of(delims, old_pos)) != std::string::npos) {
vec.emplace_back(s.substr(old_pos, pos - old_pos));
while((pos = str.find_first_of(delims, old_pos)) != std::string::npos) {
vec.emplace_back(str.substr(old_pos, pos - old_pos));
old_pos = pos + 1;
}
vec.emplace_back(std::string(s.substr(old_pos)));
vec.emplace_back(str.substr(old_pos));
return vec;
}
@ -98,22 +109,22 @@ static std::string join(const C& container, const std::string& delim) {
return str;
}
constexpr const char* const ws = " \t\n\r\f\v";
constexpr const char* const whitespace = " \t\n\r\f\v";
CPPTRACE_MAYBE_UNUSED
static std::string trim(const std::string& s) {
if(s == "") {
static std::string trim(const std::string& str) {
if(str.empty()) {
return "";
}
size_t l = s.find_first_not_of(ws);
size_t r = s.find_last_not_of(ws) + 1;
return s.substr(l, r - l);
const size_t left = str.find_first_not_of(whitespace);
const size_t right = str.find_last_not_of(whitespace) + 1;
return str.substr(left, right - left);
}
CPPTRACE_MAYBE_UNUSED
static std::string to_hex(uintptr_t addr) {
std::stringstream sstream;
sstream<<std::hex<<uintptr_t(addr);
sstream<<std::hex<<addr;
return std::move(sstream).str();
}

View File

@ -3,7 +3,7 @@
#include <string>
#ifdef _WIN32
#if defined(_WIN32)
#include <windows.h>
namespace cpptrace {
@ -20,7 +20,7 @@ namespace cpptrace {
}
}
#elif __APPLE__
#elif defined(__APPLE__)
#include <cstdint>
#include <mach-o/dyld.h>
@ -42,8 +42,9 @@ namespace cpptrace {
}
}
#elif __linux__
#elif defined(__linux__)
#include <linux/limits.h>
#include <sys/types.h>
#include <unistd.h>
namespace cpptrace {
@ -55,11 +56,11 @@ namespace cpptrace {
if(!did_init) {
did_init = true;
char buffer[PATH_MAX + 1];
ssize_t s = readlink("/proc/self/exe", buffer, PATH_MAX);
if(s == -1) {
const ssize_t size = readlink("/proc/self/exe", buffer, PATH_MAX);
if(size == -1) {
return nullptr;
}
buffer[s] = 0;
buffer[size] = 0;
name = buffer;
valid = true;
}

View File

@ -8,13 +8,13 @@
namespace cpptrace {
namespace detail {
// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
class symbolizer {
struct impl;
std::unique_ptr<impl> pimpl;
public:
symbolizer();
~symbolizer();
//stacktrace_frame resolve_frame(void* addr);
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames);
};
}

View File

@ -4,13 +4,17 @@
#include "cpptrace_symbols.hpp"
#include "../platform/cpptrace_common.hpp"
#include <stdio.h>
#include <signal.h>
#include <vector>
#include <cstdint>
#include <cstdio>
#include <string>
#include <unordered_map>
#include <utility>
#include <functional>
#include <vector>
#include <unistd.h>
#include <dlfcn.h>
// NOLINTNEXTLINE(misc-include-cleaner)
#include <sys/types.h>
#include <sys/wait.h>
@ -28,7 +32,7 @@ namespace cpptrace {
// reference: https://github.com/bminor/glibc/blob/master/debug/backtracesyms.c
std::vector<dlframe> frames;
frames.reserve(addrs.size());
for(const auto addr : addrs) {
for(const void* addr : addrs) {
Dl_info info;
dlframe frame;
frame.raw_address = reinterpret_cast<uintptr_t>(addr);
@ -47,16 +51,18 @@ namespace cpptrace {
bool has_addr2line() {
// Detects if addr2line exists by trying to invoke addr2line --help
constexpr int magic = 42;
pid_t pid = fork();
// NOLINTNEXTLINE(misc-include-cleaner)
const pid_t pid = fork();
if(pid == -1) { return false; }
if(pid == 0) { // child
close(STDOUT_FILENO);
// TODO: path
execlp("addr2line", "addr2line", "--help", nullptr);
exit(magic);
_exit(magic);
}
int status;
waitpid(pid, &status, 0);
// NOLINTNEXTLINE(misc-include-cleaner)
return WEXITSTATUS(status) == 0;
}
@ -71,12 +77,13 @@ namespace cpptrace {
};
static_assert(sizeof(pipe_t) == 2 * sizeof(int), "Unexpected struct packing");
static std::string resolve_addresses(const std::string& addresses, const std::string& executable) {
std::string resolve_addresses(const std::string& addresses, const std::string& executable) {
pipe_t output_pipe;
pipe_t input_pipe;
internal_verify(pipe(output_pipe.data) == 0);
internal_verify(pipe(input_pipe.data) == 0);
pid_t pid = fork();
// NOLINTNEXTLINE(misc-include-cleaner)
const pid_t pid = fork();
if(pid == -1) { return ""; } // error? TODO: Diagnostic
if(pid == 0) { // child
dup2(output_pipe.write_end, STDOUT_FILENO);
@ -107,24 +114,68 @@ namespace cpptrace {
}
struct symbolizer::impl {
using target_vec = std::vector<std::pair<std::string, std::reference_wrapper<stacktrace_frame>>>;
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
std::unordered_map<std::string, target_vec> get_addr2line_targets(
const std::vector<dlframe>& dlframes,
std::vector<stacktrace_frame>& trace
) {
std::unordered_map<std::string, target_vec> entries;
for(std::size_t i = 0; i < dlframes.size(); i++) {
const auto& entry = dlframes[i];
entries[entry.obj_path].emplace_back(
to_hex(entry.raw_address - entry.obj_base),
trace[i]
);
// Set what is known for now, and resolutions from addr2line should overwrite
trace[i].filename = entry.obj_path;
trace[i].symbol = entry.symbol;
}
return entries;
}
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
void update_trace(const std::string& line, size_t entry_index, const target_vec& entries_vec) {
// Result will be of the form <identifier> " at " path:line
// The path may be ?? if addr2line cannot resolve, line may be ?
// Edge cases:
// ?? ??:0
const std::size_t at_location = line.find(" at ");
std::size_t symbol_end;
std::size_t filename_start;
if(at_location != std::string::npos) {
symbol_end = at_location;
filename_start = at_location + 4;
} else {
internal_verify(line.find("?? ") == 0, "Unexpected edge case while processing addr2line output");
symbol_end = 2;
filename_start = 3;
}
auto symbol = line.substr(0, symbol_end);
auto colon = line.rfind(':');
internal_verify(colon != std::string::npos);
internal_verify(colon > filename_start);
auto filename = line.substr(filename_start, colon - filename_start);
auto line_number = line.substr(colon + 1);
if(line_number != "?") {
entries_vec[entry_index].second.get().line = std::stoi(line_number);
}
if(filename != "??") {
entries_vec[entry_index].second.get().filename = filename;
}
if(!symbol.empty()) {
entries_vec[entry_index].second.get().symbol = symbol;
}
}
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames) {
// TODO: Refactor better
std::vector<stacktrace_frame> trace(frames.size(), stacktrace_frame { 0, 0, 0, "", "" });
if(has_addr2line()) {
std::vector<dlframe> dlframes = backtrace_frames(frames);
std::unordered_map<
std::string,
std::vector<std::pair<std::string, std::reference_wrapper<stacktrace_frame>>>
> entries;
for(size_t i = 0; i < dlframes.size(); i++) {
const auto& entry = dlframes[i];
entries[entry.obj_path].push_back({
to_hex(entry.raw_address - entry.obj_base),
trace[i]
});
// Set what is known for now, and resolutions from addr2line should overwrite
trace[i].filename = entry.obj_path;
trace[i].symbol = entry.symbol;
}
const std::vector<dlframe> dlframes = backtrace_frames(frames);
const auto entries = get_addr2line_targets(dlframes, trace);
for(const auto& entry : entries) {
const auto& object_name = entry.first;
const auto& entries_vec = entry.second;
@ -136,37 +187,7 @@ namespace cpptrace {
auto output = split(trim(resolve_addresses(address_input, object_name)), "\n");
internal_verify(output.size() == entries_vec.size());
for(size_t i = 0; i < output.size(); i++) {
// Result will be of the form <identifier> " at " path:line
// The path may be ?? if addr2line cannot resolve, line may be ?
// Edge cases:
// ?? ??:0
const auto& line = output[i];
std::size_t at_location = line.find(" at ");
std::size_t symbol_end;
std::size_t filename_start;
if(at_location != std::string::npos) {
symbol_end = at_location;
filename_start = at_location + 4;
} else {
internal_verify(line.find("?? ") == 0, "Unexpected edge case while processing addr2line output");
symbol_end = 2;
filename_start = 3;
}
auto symbol = line.substr(0, symbol_end);
auto colon = line.rfind(":");
internal_verify(colon != std::string::npos);
internal_verify(colon > filename_start);
auto filename = line.substr(filename_start, colon - filename_start);
auto line_number = line.substr(colon + 1);
if(line_number != "?") {
entries_vec[i].second.get().line = std::stoi(line_number);
}
if(filename != "??") {
entries_vec[i].second.get().filename = filename;
}
if(symbol != "") {
entries_vec[i].second.get().symbol = symbol;
}
update_trace(output[i], i, entries_vec);
}
}
}
@ -174,6 +195,7 @@ namespace cpptrace {
}
};
// NOLINTNEXTLINE(bugprone-unhandled-exception-at-new)
symbolizer::symbolizer() : pimpl{new impl} {}
symbolizer::~symbolizer() = default;

View File

@ -2,8 +2,8 @@
#include <cpptrace/cpptrace.hpp>
#include "cpptrace_symbols.hpp"
#include "../platform/cpptrace_program_name.hpp"
#include <cstdint>
#include <memory>
#include <vector>
@ -12,7 +12,8 @@
namespace cpptrace {
namespace detail {
struct symbolizer::impl {
stacktrace_frame resolve_frame(void* addr) {
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
stacktrace_frame resolve_frame(const void* addr) {
Dl_info info;
if(dladdr(addr, &info)) {
return {
@ -34,6 +35,7 @@ namespace cpptrace {
}
};
// NOLINTNEXTLINE(bugprone-unhandled-exception-at-new)
symbolizer::symbolizer() : pimpl{new impl} {}
symbolizer::~symbolizer() = default;
@ -44,7 +46,7 @@ namespace cpptrace {
std::vector<stacktrace_frame> symbolizer::resolve_frames(const std::vector<void*>& frames) {
std::vector<stacktrace_frame> trace;
trace.reserve(frames.size());
for(const auto frame : frames) {
for(const void* frame : frames) {
trace.push_back(pimpl->resolve_frame(frame));
}
return trace;

View File

@ -4,6 +4,7 @@
#include "cpptrace_symbols.hpp"
#include "../platform/cpptrace_program_name.hpp"
#include <cstdint>
#include <memory>
#include <vector>
@ -42,6 +43,7 @@ namespace cpptrace {
backtrace_state* get_backtrace_state() {
// backtrace_create_state must be called only one time per program
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
static backtrace_state* state = nullptr;
static bool called = false;
if(!called) {
@ -53,7 +55,8 @@ namespace cpptrace {
// TODO: Handle backtrace_pcinfo calling the callback multiple times on inlined functions
struct symbolizer::impl {
stacktrace_frame resolve_frame(void* addr) {
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
stacktrace_frame resolve_frame(const void* addr) {
stacktrace_frame frame;
frame.col = 0;
backtrace_pcinfo(
@ -77,6 +80,7 @@ namespace cpptrace {
}
};
// NOLINTNEXTLINE(bugprone-unhandled-exception-at-new)
symbolizer::symbolizer() : pimpl{new impl} {}
symbolizer::~symbolizer() = default;
@ -87,7 +91,7 @@ namespace cpptrace {
std::vector<stacktrace_frame> symbolizer::resolve_frames(const std::vector<void*>& frames) {
std::vector<stacktrace_frame> trace;
trace.reserve(frames.size());
for(const auto frame : frames) {
for(const void* frame : frames) {
trace.push_back(pimpl->resolve_frame(frame));
}
return trace;

View File

@ -2,7 +2,6 @@
#include <cpptrace/cpptrace.hpp>
#include "cpptrace_symbols.hpp"
#include "../platform/cpptrace_program_name.hpp"
#include <vector>
@ -21,6 +20,7 @@ namespace cpptrace {
// };
// }
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
std::vector<stacktrace_frame> symbolizer::resolve_frames(const std::vector<void*>& frames) {
return std::vector<stacktrace_frame>(frames.size(), {
0,

View File

@ -1,10 +1,10 @@
#ifndef CPPTRACE_UNWIND_HPP
#define CPPTRACE_UNWIND_HPP
#include <cpptrace/cpptrace.hpp>
#include "../platform/cpptrace_common.hpp"
#include <cstddef>
#include <vector>
namespace cpptrace {
namespace detail {

View File

@ -1,10 +1,10 @@
#ifdef CPPTRACE_UNWIND_WITH_EXECINFO
#include <cpptrace/cpptrace.hpp>
#include "cpptrace_unwind.hpp"
#include "../platform/cpptrace_common.hpp"
#include <algorithm>
#include <cstddef>
#include <vector>
#include <execinfo.h>
@ -14,9 +14,9 @@ namespace cpptrace {
CPPTRACE_FORCE_NO_INLINE
std::vector<void*> capture_frames(size_t skip) {
std::vector<void*> frames(hard_max_frames + skip, nullptr);
int n_frames = backtrace(frames.data(), hard_max_frames + skip);
const int n_frames = backtrace(frames.data(), int(hard_max_frames + skip));
frames.resize(n_frames);
frames.erase(frames.begin(), frames.begin() + std::min(skip + 1, frames.size()));
frames.erase(frames.begin(), frames.begin() + ptrdiff_t(std::min(skip + 1, frames.size())));
frames.shrink_to_fit();
return frames;
}

View File

@ -1,8 +1,8 @@
#ifdef CPPTRACE_UNWIND_WITH_NOTHING
#include <cpptrace/cpptrace.hpp>
#include "cpptrace_unwind.hpp"
#include <cstddef>
#include <vector>
namespace cpptrace {