47wstring Debug::BackTrace::Capture ([[maybe_unused]]
const BackTrace::Options& options)
50 [[maybe_unused]]
unsigned int useSkipFrames = options.fSkipFrames.value_or (BackTrace::Options::sDefault_SkipFrames);
54 [[maybe_unused]]
unsigned usingMaxFrames = options.fMaxFrames.value_or (BackTrace::Options::sDefault_MaxFrames);
56#if __cpp_lib_stacktrace >= 202011 && !qCompilerAndStdLib_stacktraceLinkError_Buggy && !qCompilerAndStdLib_StdBacktraceCompile_Buggy
57 auto st = std::stacktrace::current ();
59 bool firstEntry =
true;
60 for (
const stacktrace_entry& entry : st) {
61 string eText = entry.description ();
62 bool useFileName = eText.empty ();
65 eText = entry.source_file ();
67 else if (useFileName or options.fIncludeSourceLines.value_or (BackTrace::Options::sDefault_IncludeSourceLines)) {
68 eText +=
"#" + to_string (entry.source_line ());
78 return Characters::NarrowSDK2Wide (o.str (), eIgnoreErrors);
79#elif qStroika_HasComponent_boost
80 using namespace boost;
82 auto bt = stacktrace::stacktrace ();
90 streamsize w = result.width ();
91 size_t frames = bt.size ();
95 if (useSkipFrames != 0 and frames != 0) {
96 result << L
"..." << Characters::kEOL<wchar_t>;
99 bool includeSrcLines = options.fIncludeSourceLines.value_or (BackTrace::Options::sDefault_IncludeSourceLines);
100 for (
size_t i = 0; i < frames; ++i) {
101 if (i < useSkipFrames) {
108 if (includeSrcLines) {
109 result << String::FromNarrowSDKString (boost::stacktrace::to_string (bt[i])).As<wstring> ();
112 result << String::FromNarrowSDKString (bt[i].name ()).As<wstring> ();
114 result << L
";" << Characters::kEOL<wchar_t>;
115 if (i - useSkipFrames >= usingMaxFrames) {
119 return result.str ();
120#elif qStroika_Foundation_Common_Platform_Linux
124 constexpr size_t kMaxStackSize_ = 100;
126 void* stackTraceBuf[kMaxStackSize_]{};
127 int nptrs = ::backtrace (stackTraceBuf, std::size (stackTraceBuf));
128 char** syms = ::backtrace_symbols (stackTraceBuf, nptrs);
133 auto narrow2Wide = [] (
const char* s) -> wstring {
135 for (
const char* p = s; *p !=
'\0'; ++p) {
140 [[maybe_unused]]
auto&& cleanup = Execution::Finally ([syms] ()
noexcept {
145 if (useSkipFrames != 0 and nptrs != 0) {
146 out += wstring{L
"..."} + Characters::kEOL<wchar_t>;
148 for (
int j = 0; j < nptrs; j++) {
149 if (j < useSkipFrames) {
152 wstring symStr = narrow2Wide (syms[j]);
153#if defined(__GNUC__) && defined(__GLIBCXX__)
160 const char* beginOfName = ::strchr (syms[j],
'(');
161 if (beginOfName !=
nullptr) {
164 const char* endOfName = (beginOfName ==
nullptr) ?
nullptr : ::strchr (beginOfName,
'+');
168 if (beginOfName !=
nullptr and endOfName !=
nullptr) {
170 string tmp{beginOfName, endOfName};
171 char* realname = abi::__cxa_demangle (tmp.c_str (), 0, 0, &status);
173 symStr = narrow2Wide ((
string{
static_cast<const char*
> (syms[j]), beginOfName} + realname + endOfName).c_str ());
175 if (realname !=
nullptr) {
180 out += symStr + L
";" + Characters::kEOL<wchar_t>;
181 if (j - useSkipFrames >= usingMaxFrames) {
186#elif qStroika_Foundation_Common_Platform_Windows