15 #ifdef ENABLE_CALLSTACK_TRACKING
30 using namespace basis;
45 basis::mutex &callstack_tracker::__callstack_tracker_synchronizer()
48 return __global_synch_callstacks;
65 #ifdef ENABLE_MEMORY_HOOK
73 #ifdef ENABLE_MEMORY_HOOK
77 return *_hidden_trace;
82 class callstack_records
97 callstack_tracker::callstack_tracker()
98 : _bt(new callstack_records),
114 const char *file,
int line)
119 if (_unusable)
return false;
122 printf(
"callstack_tracker::push_frame: past limit at class=%s func=%s "
123 "file=%s line=%d\n", class_name, func, file, line);
127 if (_depth > _highest) _highest = _depth;
129 _bt->_records[_depth].assign(class_name, func, file, line);
139 if (_unusable)
return false;
143 printf(
"callstack_tracker::pop_frame stack underflow!\n");
146 _bt->_records[_depth].clean();
157 if (_unusable)
return false;
158 if (!_depth)
return false;
159 _bt->_records[_depth]._line = line;
164 #define CHECK_SPACE_IN_BUFFER(desired_chunk) \
166 if (space_used_in_buffer + desired_chunk >= full_size_needed - 4) { \
167 printf("callstack_tracker::full_trace: failure in size estimation--we would have blown out of the buffer"); \
170 space_used_in_buffer += desired_chunk; \
177 if (_unusable)
return strdup(
"");
179 char *to_return = (
char *)malloc(full_size_needed);
188 char temp[initial_len];
189 int space_left_in_line;
191 int space_used_in_buffer = 0;
197 for (
int i = _depth; i >= 1; i--) {
199 strcat(to_return,
"\t");
200 space_left_in_line = initial_len;
202 int len_class = strlen(_bt->_records[i]._class);
203 int len_func = strlen(_bt->_records[i]._func);
204 if (space_left_in_line > len_class + len_func + 6) {
205 space_left_in_line -= len_class + len_func + 6;
206 sprintf(
temp,
"\"%s::%s\", ", _bt->_records[i]._class,
207 _bt->_records[i]._func);
209 strcat(to_return,
temp);
213 int len_file = strlen(_bt->_records[i]._file);
214 if (space_left_in_line > len_file + 4) {
215 space_left_in_line -= len_file + 4;
216 sprintf(
temp,
"\"%s\", ", _bt->_records[i]._file);
218 strcat(to_return,
temp);
222 sprintf(
temp,
"\"line=%d\"", _bt->_records[i]._line);
223 int len_line = strlen(
temp);
224 if (space_left_in_line > len_line) {
225 space_left_in_line -= len_line;
227 strcat(to_return,
temp);
231 strcat(to_return,
"\n");
241 if (_unusable)
return 0;
244 for (
int i = _depth; i >= 1; i--) {
249 int len_class = strlen(_bt->_records[i]._class);
250 int len_func = strlen(_bt->_records[i]._func);
251 this_line += len_class + len_func + 6;
253 int len_file = strlen(_bt->_records[i]._file);
254 this_line += len_file + 4;
268 const char *func,
const char *file,
int line,
bool add_frame)
269 : _frame_involved(add_frame),
284 : _frame_involved(false),
285 _class(to_copy._class? strdup(to_copy._class) :
NULL_POINTER),
286 _func(to_copy._func? strdup(to_copy._func) :
NULL_POINTER),
287 _file(to_copy._file? strdup(to_copy._file) :
NULL_POINTER),
311 if (
this == &to_copy)
return *
this;
312 assign(to_copy._class, to_copy._func, to_copy._file, to_copy._line);
318 const char *file,
int line)
#define CHECK_SPACE_IN_BUFFER(desired_chunk)
This object can provide a backtrace at runtime of the invoking methods.
bool push_frame(const char *class_name, const char *func, const char *file, int line)
adds a new stack from for the "class_name" in "function" at the "line".
bool pop_frame()
removes the last callstack frame off from our tracking.
virtual ~callstack_tracker()
char * full_trace() const
provides the current stack trace in a newly malloc'd string.
bool update_line(int line)
sets the line number within the current stack frame.
static basis::mutex & __callstack_tracker_synchronizer()
protects concurrent access.
int full_trace_size() const
this returns an estimated number of bytes needed for the full_trace().
a small object that represents a stack trace in progress.
frame_tracking_instance(const char *class_name="", const char *func="", const char *file="", int line=0, bool add_frame=false)
as an automatic variable, this can hang onto frame information.
~frame_tracking_instance()
releases the information and this stack frame in the tracker.
void clean()
throws out our accumulated memory and pops frame if applicable.
char * _file
newly allocated copies.
bool _frame_involved
has this object been added to the tracker?
void assign(const char *class_name, const char *func, const char *file, int line)
similar to assignment operator but doesn't require an object.
auto_synchronizer simplifies concurrent code by automatically unlocking.
#define NULL_POINTER
The value representing a pointer to nothing.
#define program_wide_memories()
Implements an application lock to ensure only one is running at once.
callstack_tracker & thread_wide_stack_trace()
the single instance of callstack_tracker.
const char * emptiness_note
what we show when the stack is empty.
void update_current_stack_frame_line_number(int line)
sets the line number for the current frame in the global stack trace.
const int MAX_STACK_DEPTH
The guards collection helps in testing preconditions and reporting errors.
void WHACK(contents *&ptr)
deletion with clearing of the pointer.