Skip to content

Commit 454623b

Browse files
author
Dimitri Rusin
committed
s
1 parent e156ada commit 454623b

File tree

1 file changed

+77
-4
lines changed

1 file changed

+77
-4
lines changed

include/ioh/common/factory.hpp

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@
33
#include <algorithm>
44
#include <cassert>
55
#include <cstdlib>
6+
#include <execinfo.h>
67
#include <functional>
78
#include <iostream>
89
#include <map>
910
#include <memory>
1011
#include <optional>
12+
#include <signal.h>
1113
#include <string>
1214
#include <type_traits>
15+
#include <unistd.h>
1316
#include <utility>
1417
#include <vector>
1518

@@ -58,6 +61,79 @@ namespace ioh::problem
5861
};
5962
} // namespace ioh::problem
6063

64+
65+
66+
67+
void print_backtrace() {
68+
const int max_frames = 64;
69+
void* addrlist[max_frames + 1];
70+
71+
// retrieve current stack addresses
72+
int addrlen = backtrace(addrlist, sizeof(addrlist) / sizeof(void*));
73+
74+
if (addrlen == 0) {
75+
std::cerr << " <empty, possibly corrupt>\n";
76+
return;
77+
}
78+
79+
// resolve addresses into strings containing "filename(function+address)",
80+
// this array must be free()-ed
81+
char** symbollist = backtrace_symbols(addrlist, addrlen);
82+
83+
// allocate string which will be filled with the demangled function name
84+
size_t funcnamesize = 256;
85+
char* funcname = (char*)malloc(funcnamesize);
86+
87+
// iterate over the returned symbol lines. skip the first, it is the
88+
// address of this function.
89+
for (int i = 1; i < addrlen; i++) {
90+
char *begin_name = nullptr, *begin_offset = nullptr, *end_offset = nullptr;
91+
92+
// find parentheses and +address offset surrounding the mangled name
93+
for (char *p = symbollist[i]; *p; ++p) {
94+
if (*p == '(')
95+
begin_name = p;
96+
else if (*p == '+')
97+
begin_offset = p;
98+
else if (*p == ')' && begin_offset) {
99+
end_offset = p;
100+
break;
101+
}
102+
}
103+
104+
if (begin_name && begin_offset && end_offset && begin_name < begin_offset) {
105+
*begin_name++ = '\0';
106+
*begin_offset++ = '\0';
107+
*end_offset = '\0';
108+
109+
// mangle the function name
110+
int status;
111+
char* ret = abi::__cxa_demangle(begin_name, funcname, &funcnamesize, &status);
112+
if (status == 0) {
113+
funcname = ret; // use possibly realloc()-ed string
114+
std::cerr << " " << symbollist[i] << " : " << funcname << "+" << begin_offset << "\n";
115+
} else {
116+
// demangling failed, output function name as a C function with no arguments
117+
std::cerr << " " << symbollist[i] << " : " << begin_name << "()+" << begin_offset << "\n";
118+
}
119+
} else {
120+
// couldn't parse the line, print the whole line
121+
std::cerr << " " << symbollist[i] << "\n";
122+
}
123+
}
124+
125+
free(funcname);
126+
free(symbollist);
127+
}
128+
129+
130+
131+
132+
133+
134+
135+
136+
61137
namespace ioh::common
62138
{
63139

@@ -142,11 +218,8 @@ namespace ioh::common
142218

143219
if (already_defined) {
144220
std::string error_message = "Error: The name '" + name + "' has already been defined in the factory.";
145-
146-
// Output the error message to both std::cerr and std::cout
147221
std::cerr << error_message << std::endl;
148-
std::cout << error_message << std::endl;
149-
222+
print_backtrace(); // Print the backtrace here
150223
assert(!already_defined && name.c_str());
151224
}
152225

0 commit comments

Comments
 (0)