18 #ifdef ENABLE_CALLSTACK_TRACKING
33 const int MAX_STACK_DEPTH = 2000;
36 const int MAX_TEXT_FIELD = 1024;
39 const char *emptiness_note =
"Empty Stack\n";
44 class callstack_records
59 callstack_tracker::callstack_tracker()
60 : _bt(new callstack_records),
70 callstack_tracker::~callstack_tracker()
78 bool callstack_tracker::push_frame(
const char *class_name,
const char *func,
79 const char *file,
int line)
82 if (_unusable)
return false;
83 if (_depth >= MAX_STACK_DEPTH) {
85 printf(
"callstack_tracker::push_frame: past limit at class=%s func=%s "
86 "file=%s line=%d\n", class_name, func, file, line);
90 if (_depth > _highest) _highest = _depth;
92 _bt->_records[_depth].assign(class_name, func, file, line);
97 bool callstack_tracker::pop_frame()
100 if (_unusable)
return false;
104 printf(
"callstack_tracker::pop_frame stack underflow!\n");
107 _bt->_records[_depth].clean();
114 bool callstack_tracker::update_line(
int line)
116 if (_unusable)
return false;
117 if (!_depth)
return false;
118 _bt->_records[_depth]._line = line;
122 char *callstack_tracker::full_trace()
const
124 if (_unusable)
return strdup(
"");
126 char *to_return = (
char *)malloc(full_trace_size());
129 strcat(to_return, emptiness_note);
132 const int initial_len = MAX_TEXT_FIELD + 8;
133 char temp[initial_len];
134 int allowed_len = initial_len;
137 for (
int i = _depth; i >= 1; i--) {
138 strcat(to_return,
"\t");
140 int len_class = strlen(_bt->_records[i]._class);
141 int len_func = strlen(_bt->_records[i]._func);
142 if (allowed_len > len_class + len_func + 6) {
143 allowed_len -= len_class + len_func + 6;
144 sprintf(temp,
"\"%s::%s\", ", _bt->_records[i]._class,
145 _bt->_records[i]._func);
146 strcat(to_return, temp);
150 int len_file = strlen(_bt->_records[i]._file);
151 if (allowed_len > len_file + 4) {
152 allowed_len -= len_file + 4;
153 sprintf(temp,
"\"%s\", ", _bt->_records[i]._file);
154 strcat(to_return, temp);
158 sprintf(temp,
"\"line=%d\"", _bt->_records[i]._line);
159 int len_line = strlen(temp);
160 if (allowed_len > len_line) {
161 allowed_len -= len_line;
162 strcat(to_return, temp);
165 strcat(to_return,
"\n");
172 int callstack_tracker::full_trace_size()
const
174 if (_unusable)
return 0;
175 if (!_depth)
return strlen(emptiness_note) + 14;
177 for (
int i = _depth; i >= 1; i--) {
182 int len_class = strlen(_bt->_records[i]._class);
183 int len_func = strlen(_bt->_records[i]._func);
184 this_line += len_class + len_func + 6;
186 int len_file = strlen(_bt->_records[i]._file);
187 this_line += len_file + 4;
192 if (this_line < MAX_TEXT_FIELD + 8) to_return += this_line;
193 else to_return += MAX_TEXT_FIELD + 8;
201 const char *func,
const char *file,
int line,
bool add_frame)
202 : _frame_involved(add_frame),
208 if (_frame_involved) {
210 program_wide_stack_trace().push_frame(class_name, func, file, line);
217 : _frame_involved(false),
218 _class(to_copy._class? strdup(to_copy._class) :
NULL_POINTER),
219 _func(to_copy._func? strdup(to_copy._func) :
NULL_POINTER),
220 _file(to_copy._file? strdup(to_copy._file) :
NULL_POINTER),
225 frame_tracking_instance::~frame_tracking_instance() { clean(); }
227 void frame_tracking_instance::clean()
229 if (_frame_involved) {
231 program_wide_stack_trace().pop_frame();
233 _frame_involved =
false;
244 if (
this == &to_copy)
return *
this;
245 assign(to_copy._class, to_copy._func, to_copy._file, to_copy._line);
250 void frame_tracking_instance::assign(
const char *class_name,
const char *func,
251 const char *file,
int line)
254 _frame_involved =
false;
264 program_wide_stack_trace().update_line(line);
#define update_current_stack_frame_line_number(line)
#define frame_tracking_instance
#define NULL_POINTER
The value representing a pointer to nothing.
void WHACK(contents *&ptr)
deletion with clearing of the pointer.