improve buffer debugging by logging the call stack of where it was allocated and freed from
This commit is contained in:
parent
9382c77ea2
commit
554812f0ab
|
@ -56,12 +56,18 @@ struct alloc_header
|
|||
{
|
||||
libtorrent::size_type size;
|
||||
int magic;
|
||||
char stack[3072];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#if defined TORRENT_DEBUG_BUFFERS && (defined __linux__ || (defined __APPLE__ && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050))
|
||||
void print_backtrace(char* out, int len);
|
||||
#endif
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
int page_size()
|
||||
{
|
||||
static int s = 0;
|
||||
|
@ -82,18 +88,21 @@ namespace libtorrent
|
|||
return s;
|
||||
}
|
||||
|
||||
char* page_aligned_allocator::malloc(const size_type bytes)
|
||||
char* page_aligned_allocator::malloc(size_type bytes)
|
||||
{
|
||||
#ifdef TORRENT_DEBUG_BUFFERS
|
||||
int page = page_size();
|
||||
char* ret = (char*)valloc(bytes + 2 * page);
|
||||
int num_pages = (bytes + (page-1)) + 2;
|
||||
char* ret = (char*)valloc(num_pages * page);
|
||||
// make the two surrounding pages non-readable and -writable
|
||||
TORRENT_ASSERT((bytes & (page-1)) == 0);
|
||||
alloc_header* h = (alloc_header*)ret;
|
||||
h->size = bytes;
|
||||
h->magic = 0x1337;
|
||||
#if defined __linux__ || (defined __APPLE__ && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
|
||||
print_backtrace(h->stack, sizeof(h->stack));
|
||||
#endif
|
||||
mprotect(ret, page, PROT_READ);
|
||||
mprotect(ret + page + bytes, page, PROT_READ);
|
||||
mprotect(ret + (num_pages-1) * page, page, PROT_READ);
|
||||
// fprintf(stderr, "malloc: %p head: %p tail: %p size: %d\n", ret + page, ret, ret + page + bytes, int(bytes));
|
||||
|
||||
return ret + page;
|
||||
|
@ -126,12 +135,15 @@ namespace libtorrent
|
|||
// make the two surrounding pages non-readable and -writable
|
||||
mprotect(block - page, page, PROT_READ | PROT_WRITE);
|
||||
alloc_header* h = (alloc_header*)(block - page);
|
||||
TORRENT_ASSERT((h->size & (page-1)) == 0);
|
||||
int num_pages = (h->size + (page-1)) + 2;
|
||||
TORRENT_ASSERT(h->magic == 0x1337);
|
||||
mprotect(block + h->size, page, PROT_READ | PROT_WRITE);
|
||||
mprotect(block + (num_pages-2) * page, page, PROT_READ | PROT_WRITE);
|
||||
// fprintf(stderr, "free: %p head: %p tail: %p size: %d\n", block, block - page, block + h->size, int(h->size));
|
||||
h->magic = 0;
|
||||
|
||||
#if defined __linux__ || (defined __APPLE__ && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
|
||||
print_backtrace(h->stack, sizeof(h->stack));
|
||||
#endif
|
||||
::free(block - page);
|
||||
return;
|
||||
#endif
|
||||
|
|
|
@ -97,16 +97,17 @@ std::string demangle(char const* name) { return name; }
|
|||
#if (defined __linux__ || (defined __APPLE__ && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050))
|
||||
#include <execinfo.h>
|
||||
|
||||
void print_backtrace(FILE* out, char const* label)
|
||||
void print_backtrace(char* out, int len)
|
||||
{
|
||||
void* stack[50];
|
||||
int size = backtrace(stack, 50);
|
||||
char** symbols = backtrace_symbols(stack, size);
|
||||
|
||||
fprintf(out, "%s\n", label);
|
||||
for (int i = 1; i < size; ++i)
|
||||
for (int i = 1; i < size && len > 0; ++i)
|
||||
{
|
||||
fprintf(out, "%d: %s\n", i, demangle(symbols[i]).c_str());
|
||||
int ret = snprintf(out, len, "%d: %s\n", i, demangle(symbols[i]).c_str());
|
||||
out += ret;
|
||||
len -= ret;
|
||||
}
|
||||
|
||||
free(symbols);
|
||||
|
@ -123,7 +124,6 @@ char const* libtorrent_assert_log = "asserts.log";
|
|||
|
||||
void assert_fail(char const* expr, int line, char const* file, char const* function, char const* value)
|
||||
{
|
||||
|
||||
#if TORRENT_PRODUCTION_ASSERTS
|
||||
FILE* out = fopen(libtorrent_assert_log, "a+");
|
||||
if (out == 0) out = stderr;
|
||||
|
@ -131,6 +131,9 @@ void assert_fail(char const* expr, int line, char const* file, char const* funct
|
|||
FILE* out = stderr;
|
||||
#endif
|
||||
|
||||
char stack[8192];
|
||||
print_backtrace(stack, sizeof(stack));
|
||||
|
||||
fprintf(out, "assertion failed. Please file a bugreport at "
|
||||
"http://code.rasterbar.com/libtorrent/newticket\n"
|
||||
"Please include the following information:\n\n"
|
||||
|
@ -140,11 +143,12 @@ void assert_fail(char const* expr, int line, char const* file, char const* funct
|
|||
"line: %d\n"
|
||||
"function: %s\n"
|
||||
"expression: %s\n"
|
||||
"%s%s"
|
||||
"%s%s\n"
|
||||
"stack:\n"
|
||||
"%s\n"
|
||||
, LIBTORRENT_REVISION, file, line, function, expr
|
||||
, value ? value : "", value ? "\n" : "");
|
||||
|
||||
print_backtrace(out, "stack:");
|
||||
, value ? value : "", value ? "\n" : ""
|
||||
, stack);
|
||||
|
||||
// if production asserts are defined, don't abort, just print the error
|
||||
#if TORRENT_PRODUCTION_ASSERTS
|
||||
|
|
Loading…
Reference in New Issue