1//---------------------------------------------------------------------------- 2// Anti-Grain Geometry - Version 2.2 3// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) 4// 5// Permission to copy, use, modify, sell and distribute this software 6// is granted provided this copyright notice appears in all copies. 7// This software is provided "as is" without express or implied 8// warranty, and with no claim as to its suitability for any purpose. 9// 10//---------------------------------------------------------------------------- 11// Contact: mcseem@antigrain.com 12// mcseemagg@yahoo.com 13// http://www.antigrain.com 14//---------------------------------------------------------------------------- 15// 16// Debuging stuff for catching memory leaks and corruptions 17// 18//---------------------------------------------------------------------------- 19#include <stdio.h> 20#include <stdlib.h> 21#include <string.h> 22#include <stdarg.h> 23#include "dbg_new/agg_dbg_new.h" 24 25namespace agg 26{ 27 28 int dbg_new_level = -1; 29 30 struct dbg_new 31 { 32 unsigned new_count; 33 unsigned del_count; 34 unsigned new_bytes; 35 unsigned del_bytes; 36 unsigned max_count; 37 unsigned max_bytes; 38 unsigned corrupted_count; 39 char file_name[512]; 40 int line; 41 bool report_all; 42 }; 43 44 dbg_new dbg_new_info[max_dbg_new_level] = 45 { 46 { 0, 0, 0, 0, 0, 0, 0, "", 0, false }, 47 }; 48 49#ifdef AGG_DBG_NEW_CHECK_ADDR 50 void* dbg_new_allocations[max_allocations] = 51 { 52 0, 53 }; 54 unsigned dbg_new_prev_word[max_allocations] = 55 { 56 0, 57 }; 58 59 60 unsigned dbg_new_max_count = 0; 61#endif 62 63 64 //------------------------------------------------------------------------ 65 void add_allocated_addr(void* ptr) 66 { 67#ifdef AGG_DBG_NEW_CHECK_ADDR 68 if(dbg_new_max_count >= max_allocations) 69 { 70 printf("ADDR_CHECK: limit exceeded\n"); 71 } 72 dbg_new_allocations[dbg_new_max_count] = ptr; 73 memcpy(dbg_new_prev_word + dbg_new_max_count, 74 ((char*)ptr) - sizeof(unsigned), 75 sizeof(unsigned)); 76 dbg_new_max_count++; 77#endif 78 } 79 80 81 //------------------------------------------------------------------------ 82 bool check_and_remove_allocated_addr(void* ptr) 83 { 84#ifdef AGG_DBG_NEW_CHECK_ADDR 85 unsigned i; 86 for(i = 0; i < dbg_new_max_count; i++) 87 { 88 if(dbg_new_allocations[i] == ptr) 89 { 90 unsigned prev; 91 memcpy(&prev, 92 ((char*)ptr) - sizeof(unsigned), 93 sizeof(unsigned)); 94 95 if(prev != dbg_new_prev_word[i]) 96 { 97 printf("MEMORY CORRUPTION AT %08x prev=%08x cur=%08x\n", ptr, prev, dbg_new_prev_word[i]); 98 //return false; 99 } 100 101 if(i < dbg_new_max_count - 1) 102 { 103 memmove(dbg_new_allocations + i, 104 dbg_new_allocations + i + 1, 105 sizeof(void*) * dbg_new_max_count - i - 1); 106 } 107 dbg_new_max_count--; 108 //printf("free ok\n"); 109 return true; 110 } 111 } 112 printf("ATTEMPT TO FREE BAD ADDRESS %08x\n", ptr); 113 return false; 114#else 115 return true; 116#endif 117 } 118 119 120 //------------------------------------------------------------------------ 121 watchdoggy::watchdoggy(const char* file, int line, bool report_all) 122 { 123 #ifdef _WIN32 124 if(dbg_new_level == -1) 125 { 126 FILE* fd = fopen("stdout.txt", "w"); 127 fclose(fd); 128 } 129 #endif 130 131 dbg_new_level++; 132 ::memset(dbg_new_info + dbg_new_level, 0, sizeof(dbg_new)); 133 if(file == 0) file = ""; 134 int len = strlen(file); 135 if(len > 511) len = 511; 136 ::memcpy(dbg_new_info[dbg_new_level].file_name, file, len); 137 dbg_new_info[dbg_new_level].file_name[len] = 0; 138 dbg_new_info[dbg_new_level].line = line; 139 dbg_new_info[dbg_new_level].report_all = report_all; 140 printf("wd%d started. File:%s line:%d\n", 141 dbg_new_level, 142 file, 143 line); 144 } 145 146 147 //------------------------------------------------------------------------ 148 watchdoggy::~watchdoggy() 149 { 150 if(dbg_new_level >= 0) 151 { 152 printf("wd%d stopped. File:%s line:%d\n", 153 dbg_new_level, 154 dbg_new_info[dbg_new_level].file_name, 155 dbg_new_info[dbg_new_level].line); 156 printf("new_count=%u del_count=%u max_count=%u balance=%d\n" 157 "new_bytes=%u del_bytes=%u max_bytes=%u balance=%d " 158 "corrupted_count=%u\n", 159 dbg_new_info[dbg_new_level].new_count, 160 dbg_new_info[dbg_new_level].del_count, 161 dbg_new_info[dbg_new_level].max_count, 162 int(dbg_new_info[dbg_new_level].new_count - 163 dbg_new_info[dbg_new_level].del_count), 164 dbg_new_info[dbg_new_level].new_bytes, 165 dbg_new_info[dbg_new_level].del_bytes, 166 dbg_new_info[dbg_new_level].max_bytes, 167 int(dbg_new_info[dbg_new_level].new_bytes - 168 dbg_new_info[dbg_new_level].del_bytes), 169 dbg_new_info[dbg_new_level].corrupted_count 170 ); 171 dbg_new_level--; 172 } 173 } 174 175 176 //------------------------------------------------------------------------ 177 // 178 // This code implements the AUTODIN II polynomial 179 // The variable corresponding to the macro argument "crc" should 180 // be an unsigned long. 181 // Oroginal code by Spencer Garrett <srg@quick.com> 182 // 183 // generated using the AUTODIN II polynomial 184 // x^32 + x^26 + x^23 + x^22 + x^16 + 185 // x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1 186 // 187 //------------------------------------------------------------------------ 188 static const unsigned crc32tab[256] = 189 { 190 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 191 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 192 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 193 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 194 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 195 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 196 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 197 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 198 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 199 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 200 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 201 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 202 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 203 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 204 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 205 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 206 207 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 208 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 209 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 210 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 211 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 212 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 213 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 214 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 215 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 216 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 217 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 218 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 219 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 220 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 221 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 222 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 223 224 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 225 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 226 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 227 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 228 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 229 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 230 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 231 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 232 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 233 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 234 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 235 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 236 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 237 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 238 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 239 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 240 241 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 242 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 243 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 244 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 245 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 246 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 247 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 248 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 249 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 250 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 251 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 252 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 253 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 254 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 255 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 256 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d 257 }; 258 259 260 //------------------------------------------------------------------------ 261 static unsigned long calcCRC32(const char* buf, unsigned size) 262 { 263 unsigned long crc = (unsigned long)~0; 264 const char* p; 265 unsigned len = 0; 266 unsigned nr = size; 267 268 for (len += nr, p = buf; nr--; ++p) 269 { 270 crc = (crc >> 8) ^ crc32tab[(crc ^ *p) & 0xff]; 271 } 272 return ~crc; 273 } 274 275 276 277 278 279 //------------------------------------------------------------------------ 280 void* dbg_malloc(unsigned size, const char* file, int line) 281 { 282 if(dbg_new_level < 0) 283 { 284 void* ptr = ::malloc(size); 285 printf("%u allocated at %08x %s %d\n", size, ptr, file, line); 286 add_allocated_addr(ptr); 287 return ptr; 288 } 289 290 // The structure of the allocated memory: 291 // 292 // [USER_SIZE:16 bytes] //allows for keeping proper data alignment 293 // [USER_MEM] 294 // [CRC32_sum:long, actual size depends on architecture] 295 // [test_bytes:256 bytes] //should be enough for checking non-fatal 296 // //corruptions with keeping the line number 297 // //and filename correct 298 // [line:unsigned] 299 // [strlen:unsigned] 300 // [file_name:zero_end_string] 301 302 unsigned fname_len = ::strlen(file) + 1; 303 unsigned total_size = 16 + // size 304 size + // user_mem 305 sizeof(unsigned long) + // crc32 306 256 + // zero_bytes 307 sizeof(unsigned) + // line 308 sizeof(unsigned) + // strlen 309 fname_len; // .cpp file_name 310 311 char* inf_ptr = (char*)::malloc(total_size); 312 char* ret_ptr = inf_ptr + 16; 313 314 int i; 315 for(i = 0; i < 16; i++) 316 { 317 inf_ptr[i] = (char)(15-i); 318 } 319 ::memcpy(inf_ptr, &size, sizeof(unsigned)); 320 321 unsigned long crc32_before = calcCRC32(inf_ptr, 16); 322 323 inf_ptr += 16 + size; 324 char* crc32_ptr = inf_ptr; 325 inf_ptr += sizeof(unsigned long); 326 327 for(i = 0; i < 256; i++) 328 { 329 *inf_ptr++ = (char)(255-i); 330 } 331 332 ::memcpy(inf_ptr, &line, sizeof(unsigned)); 333 inf_ptr += sizeof(unsigned); 334 335 ::memcpy(inf_ptr, &fname_len, sizeof(unsigned)); 336 inf_ptr += sizeof(unsigned); 337 338 ::strcpy(inf_ptr, file); 339 340 unsigned long // long just in case 341 crc32_sum = calcCRC32(crc32_ptr + sizeof(unsigned long), 342 256 + 343 sizeof(unsigned) + 344 sizeof(unsigned) + 345 fname_len); 346 347 crc32_sum ^= crc32_before; 348 349 ::memcpy(crc32_ptr, &crc32_sum, sizeof(unsigned long)); 350 351 dbg_new_info[dbg_new_level].new_count++; 352 dbg_new_info[dbg_new_level].new_bytes += size; 353 int balance = int(dbg_new_info[dbg_new_level].new_count - 354 dbg_new_info[dbg_new_level].del_count); 355 356 if(balance > 0) 357 { 358 if(balance > int(dbg_new_info[dbg_new_level].max_count)) 359 { 360 dbg_new_info[dbg_new_level].max_count = unsigned(balance); 361 } 362 } 363 364 365 balance = int(dbg_new_info[dbg_new_level].new_bytes - 366 dbg_new_info[dbg_new_level].del_bytes); 367 368 if(balance > 0) 369 { 370 if(balance > int(dbg_new_info[dbg_new_level].max_bytes)) 371 { 372 dbg_new_info[dbg_new_level].max_bytes = unsigned(balance); 373 } 374 } 375 376 377 if(dbg_new_info[dbg_new_level].report_all) 378 { 379 printf("wdl%d. %u allocated %08x. %s, %d\n", 380 dbg_new_level, 381 size, 382 ret_ptr, 383 file, 384 line 385 ); 386 } 387 388 add_allocated_addr(ret_ptr); 389 return ret_ptr; 390 } 391 392 393 394 //------------------------------------------------------------------------ 395 void dbg_free(void* ptr) 396 { 397 if(ptr == 0) 398 { 399 //printf("Null pointer free\n"); 400 return; 401 } 402 403 if(!check_and_remove_allocated_addr(ptr)) return; 404 405 if(dbg_new_level < 0) 406 { 407 printf("free at %08x\n", ptr); 408 ::free(ptr); 409 return; 410 } 411 412 char* free_ptr = (char*)ptr; 413 char* inf_ptr = free_ptr; 414 free_ptr -= 16; 415 416 unsigned size; 417 ::memcpy(&size, free_ptr, sizeof(unsigned)); 418 419 unsigned long crc32_before = calcCRC32(free_ptr, 16); 420 421 inf_ptr += size; 422 unsigned long crc32_sum; 423 ::memcpy(&crc32_sum, inf_ptr, sizeof(unsigned long)); 424 inf_ptr += sizeof(unsigned long); 425 char* crc32_ptr = inf_ptr; 426 427 inf_ptr += 256; 428 429 unsigned line; 430 ::memcpy(&line, inf_ptr, sizeof(unsigned)); 431 inf_ptr += sizeof(unsigned); 432 433 unsigned fname_len; 434 ::memcpy(&fname_len, inf_ptr, sizeof(unsigned)); 435 inf_ptr += sizeof(unsigned); 436 437 char file[512]; 438 if(fname_len > 511) fname_len = 511; 439 ::memcpy(file, inf_ptr, fname_len); 440 file[fname_len] = 0; 441 442 if(crc32_sum != (calcCRC32(crc32_ptr, 443 256 + 444 sizeof(unsigned) + 445 sizeof(unsigned) + 446 fname_len) ^ crc32_before)) 447 { 448 printf("WD%d:MEMORY CORRUPTION AT %08x. Allocated %u bytes in %s, line %d\n", 449 dbg_new_level, 450 ptr, 451 size, 452 file, 453 line); 454 dbg_new_info[dbg_new_level].corrupted_count++; 455 } 456 else 457 { 458 ::free(free_ptr); 459 460 dbg_new_info[dbg_new_level].del_count++; 461 dbg_new_info[dbg_new_level].del_bytes += size; 462 463 if(dbg_new_info[dbg_new_level].report_all) 464 { 465 printf("wdl%d. %u freed %08x. %s, %d\n", 466 dbg_new_level, 467 size, 468 free_ptr, 469 file, 470 line 471 ); 472 } 473 } 474 } 475} 476 477#ifdef new 478#undef new 479#endif 480 481//---------------------------------------------------------------------------- 482void* operator new (size_t size, const char* file, int line) 483{ 484 return agg::dbg_malloc(size, file, line); 485} 486 487//---------------------------------------------------------------------------- 488void* operator new [] (size_t size, const char* file, int line) 489{ 490 return agg::dbg_malloc(size, file, line); 491} 492 493//---------------------------------------------------------------------------- 494void operator delete(void *ptr) throw() 495{ 496 agg::dbg_free(ptr); 497} 498 499//---------------------------------------------------------------------------- 500void operator delete [] (void *ptr) throw() 501{ 502 agg::dbg_free(ptr); 503} 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518/* 519#include "dbg_new/agg_dbg_new.h" 520 521int main() 522{ 523 AGG_WATCHDOGGY(wd1, true); 524 int* a = new int[100]; 525 a[100] = 0; 526 527 delete [] a; 528 return 0; 529} 530*/ 531 532 533 534 535 536 537 538 539