/* * * Copyright (c) 1998-2000 * Dr John Maddock * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Dr John Maddock makes no representations * about the suitability of this software for any purpose. * It is provided "as is" without express or implied warranty. * */ /* * LOCATION: see http://www.boost.org for most recent version. * FILE: regex_debug.cpp * VERSION: 3.00 * DESCRIPTION: Misc. debugging helpers. */ #include #include #include #include #ifdef BOOST_MSVC #include #endif #ifdef BOOST_RE_DEBUG namespace boost { namespace re_detail { ostream& operator<<(ostream& s, syntax_element_type x) { return s << static_cast(x); } }} // namespace boost::re_detail namespace { char b1[32] = {0,}; char guard_pattern[32] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, }; char b2[32] = {0,}; static const int guard_size = 32; bool check_pattern(void* p) { return p ? memcmp(p, guard_pattern, guard_size) : 0; } inline unsigned maxi(unsigned i, unsigned j) { return i < j ? j : i; } unsigned int allocated = 0; struct init { init(); ~init(); }; init::init() { #ifdef BOOST_MSVC _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_DELAY_FREE_MEM_DF|_CRTDBG_LEAK_CHECK_DF); #endif } init::~init() { } init i; void* get_mem(size_t n) { ++allocated; char* p = (char*)malloc(n + guard_size * 2 + maxi(sizeof(int) + sizeof(void*), boost::re_detail::padding_size) + boost::re_detail::padding_size); char* base = p; p = (char*)((std::ptrdiff_t)(p + boost::re_detail::padding_mask) & ~boost::re_detail::padding_mask); std::memcpy(p + maxi(sizeof(int) + sizeof(void*), boost::re_detail::padding_size), guard_pattern, guard_size); std::memcpy(p + maxi(sizeof(int) + sizeof(void*), boost::re_detail::padding_size) + guard_size + n, guard_pattern, guard_size); *(int*)p = n; *(void**)(p + sizeof(int)) = base; return p + guard_size + maxi(sizeof(int) + sizeof(void*), boost::re_detail::padding_size); } void free_mem(void* b) { if(b) { char* p = (char*)b; p -= (guard_size + maxi(sizeof(int) + sizeof(void*), boost::re_detail::padding_size)); if(check_pattern(p + maxi(sizeof(int) + sizeof(void*), boost::re_detail::padding_size)) || check_pattern(p + maxi(sizeof(int) + sizeof(void*), boost::re_detail::padding_size) + guard_size + *(int*)p)) { cerr << "Error: freed memory has been written past end..." << endl; } free(*(void**)(p + sizeof(int))); --allocated; } } } // namespace void* operator new(size_t n) { return get_mem(n); } void* operator new[](size_t n) { return get_mem(n); } void operator delete(void* p) { free_mem(p); } void operator delete[](void* p) { free_mem(p); } #include namespace boost{ namespace re_detail{ std::set >* patterns = 0; int pattern_count = 0; void check_patterns(const char* f, int l) { if(pattern_count) { std::set >::iterator i, j; i = patterns->begin(); j = patterns->end(); while(i != j) { if(check_pattern((void*)(*i)->g1) || check_pattern((*i)->g2) || check_pattern((void*)(*i)->pc) || check_pattern((*i)->pnc)) { cerr << "Error: static memory corruption at " << hex << *i << dec << " in " << (*i)->file << "@" << (*i)->line << " called from " << f << "@" << l << endl; } ++i; } } } debug_guard::debug_guard(const char* f, int l, const char* p1, char* p2) { if(++pattern_count == 1) patterns = new std::set >; file = f; line = l; std::memcpy(g1, guard_pattern, guard_size); std::memcpy(g2, guard_pattern, guard_size); if(p1) { pc = p1; } else pc = 0; if(p2) { pnc = p2; std::memcpy(pnc, guard_pattern, guard_size); } else pnc = 0; patterns->insert(this); } debug_guard::~debug_guard() { check_patterns(file, line); if(check_pattern(g1) || check_pattern(g2)) { cerr << "Error: memory corruption " << file << "@" << line << endl; } patterns->erase(this); if(--pattern_count == 0) { delete patterns; patterns = 0; } } } // namespace re_detail } // namespace boost #endif