46wstring Debug::BackTrace::Capture ([[maybe_unused]]
const BackTrace::Options& options)
48 [[maybe_unused]]
unsigned int useSkipFrames = options.fSkipFrames.value_or (BackTrace::Options::sDefault_SkipFrames);
52 [[maybe_unused]]
unsigned usingMaxFrames = options.fMaxFrames.value_or (BackTrace::Options::sDefault_MaxFrames);
54#if __cpp_lib_stacktrace >= 202011 && !qCompilerAndStdLib_stacktraceLinkError_Buggy && !qCompilerAndStdLib_StdBacktraceCompile_Buggy
55 auto st = std::stacktrace::current ();
57 bool firstEntry =
true;
58 for (
const stacktrace_entry& entry : st) {
59 string eText = entry.description ();
60 bool useFileName = eText.empty ();
63 eText = entry.source_file ();
65 else if (useFileName or options.fIncludeSourceLines.value_or (BackTrace::Options::sDefault_IncludeSourceLines)) {
66 eText +=
"#" + to_string (entry.source_line ());
76 return Characters::NarrowSDK2Wide (o.str (), eIgnoreErrors);
77#elif qStroika_HasComponent_boost
78 using namespace boost;
80 auto bt = stacktrace::stacktrace ();
88 streamsize w = result.width ();
89 size_t frames = bt.size ();
93 if (useSkipFrames != 0 and frames != 0) {
94 result << L
"..." << Characters::kEOL<wchar_t>;
97 bool includeSrcLines = options.fIncludeSourceLines.value_or (BackTrace::Options::sDefault_IncludeSourceLines);
98 for (
size_t i = 0; i < frames; ++i) {
99 if (i < useSkipFrames) {
106 if (includeSrcLines) {
107 result << String::FromNarrowSDKString (boost::stacktrace::to_string (bt[i])).As<wstring> ();
110 result << String::FromNarrowSDKString (bt[i].name ()).As<wstring> ();
112 result << L
";" << Characters::kEOL<wchar_t>;
113 if (i - useSkipFrames >= usingMaxFrames) {
117 return result.str ();
118#elif qStroika_Foundation_Common_Platform_Linux
122 constexpr size_t kMaxStackSize_ = 100;
124 void* stackTraceBuf[kMaxStackSize_]{};
125 int nptrs = ::backtrace (stackTraceBuf, Memory::NEltsOf (stackTraceBuf));
126 char** syms = ::backtrace_symbols (stackTraceBuf, nptrs);
131 auto narrow2Wide = [] (
const char* s) -> wstring {
133 for (
const char* p = s; *p !=
'\0'; ++p) {
143 if (useSkipFrames != 0 and nptrs != 0) {
144 out += wstring{L
"..."} + Characters::kEOL<wchar_t>;
146 for (
int j = 0; j < nptrs; j++) {
147 if (j < useSkipFrames) {
150 wstring symStr = narrow2Wide (syms[j]);
151#if defined(__GNUC__) && defined(__GLIBCXX__)
158 const char* beginOfName = ::strchr (syms[j],
'(');
159 if (beginOfName !=
nullptr) {
162 const char* endOfName = (beginOfName ==
nullptr) ?
nullptr : ::strchr (beginOfName,
'+');
166 if (beginOfName !=
nullptr and endOfName !=
nullptr) {
168 string tmp{beginOfName, endOfName};
169 char* realname = abi::__cxa_demangle (tmp.c_str (), 0, 0, &status);
171 symStr = narrow2Wide ((
string{
static_cast<const char*
> (syms[j]), beginOfName} + realname + endOfName).c_str ());
173 if (realname !=
nullptr) {
178 out += symStr + L
";" + Characters::kEOL<wchar_t>;
179 if (j - useSkipFrames >= usingMaxFrames) {
184#elif qStroika_Foundation_Common_Platform_Windows