15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2005, Google Inc. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All rights reserved. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met: 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Redistributions of source code must retain the above copyright 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Redistributions in binary form must reproduce the above 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution. 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Neither the name of Google Inc. nor the names of its 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --- 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: Maxim Lifantsev 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Running: 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ./heap-checker_unittest 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If the unittest crashes because it can't find pprof, try: 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PPROF_PATH=/usr/local/someplace/bin/pprof ./heap-checker_unittest 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// To test that the whole-program heap checker will actually cause a leak, try: 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HEAPCHECK_TEST_LEAK= ./heap-checker_unittest 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HEAPCHECK_TEST_LOOP_LEAK= ./heap-checker_unittest 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: Both of the above commands *should* abort with an error message. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CAVEAT: Do not use vector<> and string on-heap objects in this test, 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// otherwise the test can sometimes fail for tricky leak checks 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// when we want some allocated object not to be found live by the heap checker. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This can happen with memory allocators like tcmalloc that can allocate 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// heap objects back to back without any book-keeping data in between. 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// What happens is that end-of-storage pointers of a live vector 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (or a string depending on the STL implementation used) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// can happen to point to that other heap-allocated 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// object that is not reachable otherwise and that 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we don't want to be reachable. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The implication of this for real leak checking 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is just one more chance for the liveness flood to be inexact 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (see the comment in our .h file). 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "config_for_unittests.h" 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_POLL_H 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <poll.h> 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined HAVE_STDINT_H 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdint.h> // to get uint16_t (ISO naming madness) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined HAVE_INTTYPES_H 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <inttypes.h> // another place uint16_t might be defined 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h> 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> // errno 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_UNISTD_H 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h> // for sleep(), geteuid() 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_MMAP 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/mman.h> 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h> // for open(), close() 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_EXECINFO_H 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <execinfo.h> // backtrace 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_GRP_H 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <grp.h> // getgrent, getgrnam 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_PWD_H 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pwd.h> 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iostream> // for cout 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iomanip> // for hex 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <list> 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <memory> 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/commandlineflags.h" 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/googleinit.h" 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/commandlineflags.h" 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/thread_lister.h" 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gperftools/heap-checker.h> 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "memory_region_map.h" 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gperftools/malloc_extension.h> 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gperftools/stacktrace.h> 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// On systems (like freebsd) that don't define MAP_ANONYMOUS, use the old 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// form of the name instead. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef MAP_ANONYMOUS 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define MAP_ANONYMOUS MAP_ANON 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace std; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ========================================================================= // 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(maxim): write a shell script to test that these indeed crash us 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (i.e. we do detect leaks) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Maybe add more such crash tests. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(test_leak, 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToBool("HEAP_CHECKER_TEST_TEST_LEAK", false), 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If should cause a leak crash"); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(test_loop_leak, 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToBool("HEAP_CHECKER_TEST_TEST_LOOP_LEAK", false), 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If should cause a looped leak crash"); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(test_register_leak, 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToBool("HEAP_CHECKER_TEST_TEST_REGISTER_LEAK", false), 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If should cause a leak crash by hiding a pointer " 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "that is only in a register"); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(test_cancel_global_check, 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToBool("HEAP_CHECKER_TEST_TEST_CANCEL_GLOBAL_CHECK", false), 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If should test HeapLeakChecker::CancelGlobalCheck " 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "when --test_leak or --test_loop_leak are given; " 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "the test should not fail then"); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(maybe_stripped, 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToBool("HEAP_CHECKER_TEST_MAYBE_STRIPPED", true), 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If we think we can be a stripped binary"); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(interfering_threads, 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToBool("HEAP_CHECKER_TEST_INTERFERING_THREADS", true), 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If we should use threads trying " 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "to interfere with leak checking"); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(hoarding_threads, 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToBool("HEAP_CHECKER_TEST_HOARDING_THREADS", true), 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If threads (usually the manager thread) are known " 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "to retain some old state in their global buffers, " 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "so that it's hard to force leaks when threads are around"); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(maxim): Chage the default to false 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when the standard environment used NTPL threads: 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // they do not seem to have this problem. 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(no_threads, 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToBool("HEAP_CHECKER_TEST_NO_THREADS", false), 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If we should not use any threads"); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is used so we can make can_create_leaks_reliably true 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for any pthread implementation and test with that. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DECLARE_int64(heap_check_max_pointer_offset); // heap-checker.cc 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DECLARE_string(heap_check); // in heap-checker.cc 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define WARN_IF(cond, msg) LOG_IF(WARNING, cond, msg) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is an evil macro! Be very careful using it... 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef VLOG // and we start by evilling overriding logging.h VLOG 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VLOG(lvl) if (FLAGS_verbose >= (lvl)) cout << "\n" 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is, likewise, evil 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define LOGF VLOG(INFO) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void RunHeapBusyThreads(); // below 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Closure { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~Closure() { } 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Run() = 0; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Callback0 : public Closure { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef void (*FunctionSignature)(); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline Callback0(FunctionSignature f) : f_(f) {} 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Run() { (*f_)(); delete this; } 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FunctionSignature f_; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class P1> class Callback1 : public Closure { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef void (*FunctionSignature)(P1); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline Callback1<P1>(FunctionSignature f, P1 p1) : f_(f), p1_(p1) {} 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Run() { (*f_)(p1_); delete this; } 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FunctionSignature f_; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) P1 p1_; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class P1, class P2> class Callback2 : public Closure { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef void (*FunctionSignature)(P1,P2); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline Callback2<P1,P2>(FunctionSignature f, P1 p1, P2 p2) : f_(f), p1_(p1), p2_(p2) {} 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Run() { (*f_)(p1_, p2_); delete this; } 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FunctionSignature f_; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) P1 p1_; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) P2 p2_; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Callback0* NewCallback(void (*function)()) { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new Callback0(function); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class P1> 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Callback1<P1>* NewCallback(void (*function)(P1), P1 p1) { 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new Callback1<P1>(function, p1); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class P1, class P2> 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Callback2<P1,P2>* NewCallback(void (*function)(P1,P2), P1 p1, P2 p2) { 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new Callback2<P1,P2>(function, p1, p2); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Set to true at end of main, so threads know. Not entirely thread-safe!, 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// but probably good enough. 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool g_have_exited_main = false; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If we can reliably create leaks (i.e. make leaked object 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// really unreachable from any global data). 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool can_create_leaks_reliably = false; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We use a simple allocation wrapper 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to make sure we wipe out the newly allocated objects 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in case they still happened to contain some pointer data 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// accidentally left by the memory allocator. 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Initialized { }; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static Initialized initialized; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* operator new(size_t size, const Initialized&) { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Below we use "p = new(initialized) Foo[1];" and "delete[] p;" 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // instead of "p = new(initialized) Foo;" 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when we need to delete an allocated object. 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* p = malloc(size); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(p, 0, size); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return p; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* operator new[](size_t size, const Initialized&) { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* p = new char[size]; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(p, 0, size); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return p; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DoWipeStack(int n); // defined below 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void WipeStack() { DoWipeStack(20); } 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void Pause() { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) poll(NULL, 0, 77); // time for thread activity in HeapBusyThreadBody 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Indirectly test malloc_extension.*: 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(MallocExtension::instance()->VerifyAllMemory()); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int blocks; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t total; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int histogram[kMallocHistogramSize]; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MallocExtension::instance() 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ->MallocMemoryStats(&blocks, &total, histogram) && total != 0) { 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(3) << "Malloc stats: " << blocks << " blocks of " 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << total << " bytes"; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kMallocHistogramSize; ++i) { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (histogram[i]) { 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(3) << " Malloc histogram at " << i << " : " << histogram[i]; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WipeStack(); // e.g. MallocExtension::VerifyAllMemory 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can leave pointers to heap objects on stack 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Make gcc think a pointer is "used" 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class T> 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void Use(T** foo) { 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << "Dummy-using " << static_cast<void*>(*foo) << " at " << foo; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Arbitrary value, but not such that xor'ing with it is likely 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to map one valid pointer to another valid pointer: 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const uintptr_t kHideMask = 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<uintptr_t>(0xF03A5F7BF03A5F7BLL); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helpers to hide a pointer from live data traversal. 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We just xor the pointer so that (with high probability) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it's not a valid address of a heap object anymore. 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Both Hide and UnHide must be executed within RunHidden() below 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to prevent leaving stale data on active stack that can be a pointer 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to a heap object that is not actually reachable via live variables. 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (UnHide might leave heap pointer value for an object 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that will be deallocated but later another object 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// can be allocated at the same heap address.) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class T> 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void Hide(T** ptr) { 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we cast values, not dereferenced pointers, so no aliasing issues: 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ptr = reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(*ptr) ^ kHideMask); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << "hid: " << static_cast<void*>(*ptr); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class T> 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void UnHide(T** ptr) { 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << "unhiding: " << static_cast<void*>(*ptr); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we cast values, not dereferenced pointers, so no aliasing issues: 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ptr = reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(*ptr) ^ kHideMask); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void LogHidden(const char* message, const void* ptr) { 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOGF << message << " : " 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ptr << " ^ " << reinterpret_cast<void*>(kHideMask) << endl; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// volatile to fool the compiler against inlining the calls to these 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void (*volatile run_hidden_ptr)(Closure* c, int n); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void (*volatile wipe_stack_ptr)(int n); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DoRunHidden(Closure* c, int n) { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (n) { 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(10) << "Level " << n << " at " << &n; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*run_hidden_ptr)(c, n-1); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*wipe_stack_ptr)(n); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sleep(0); // undo -foptimize-sibling-calls 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c->Run(); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*static*/ void DoWipeStack(int n) { 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(10) << "Wipe level " << n << " at " << &n; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (n) { 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int sz = 30; 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) volatile int arr[sz]; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < sz; ++i) arr[i] = 0; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*wipe_stack_ptr)(n-1); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sleep(0); // undo -foptimize-sibling-calls 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This executes closure c several stack frames down from the current one 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and then makes an effort to also wipe out the stack data that was used by 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the closure. 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This way we prevent leak checker from finding any temporary pointers 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of the closure execution on the stack and deciding that 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// these pointers (and the pointed objects) are still live. 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void RunHidden(Closure* c) { 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoRunHidden(c, 15); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoWipeStack(20); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DoAllocHidden(size_t size, void** ptr) { 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* p = new(initialized) char[size]; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Hide(&p); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&p); // use only hidden versions 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << "Allocated hidden " << p << " at " << &p; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ptr = p; // assign the hidden versions 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void* AllocHidden(size_t size) { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* r; 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunHidden(NewCallback(DoAllocHidden, size, &r)); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return r; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DoDeAllocHidden(void** ptr) { 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(ptr); // use only hidden versions 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* p = *ptr; 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << "Deallocating hidden " << p; 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnHide(&p); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete [] reinterpret_cast<char*>(p); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DeAllocHidden(void** ptr) { 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunHidden(NewCallback(DoDeAllocHidden, ptr)); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ptr = NULL; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(ptr); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PreventHeapReclaiming(size_t size) { 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef NDEBUG 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (true) { 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void** no_reclaim_list = NULL; 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(size >= sizeof(void*)); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can't use malloc_reclaim_memory flag in opt mode as debugallocation.cc 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is not used. Instead we allocate a bunch of heap objects that are 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of the same size as what we are going to leak to ensure that the object 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we are about to leak is not at the same address as some old allocated 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and freed object that might still have pointers leading to it. 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < 100; ++i) { 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void** p = reinterpret_cast<void**>(new(initialized) char[size]); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p[0] = no_reclaim_list; 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) no_reclaim_list = p; 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool RunSilent(HeapLeakChecker* check, 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool (HeapLeakChecker::* func)()) { 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // By default, don't print the 'we detected a leak' message in the 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cases we're expecting a leak (we still print when --v is >= 1). 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This way, the logging output is less confusing: we only print 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "we detected a leak", and how to diagnose it, for *unexpected* leaks. 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 old_FLAGS_verbose = FLAGS_verbose; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!VLOG_IS_ON(1)) // not on a verbose setting 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_verbose = FATAL; // only log fatal errors 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool retval = (check->*func)(); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_verbose = old_FLAGS_verbose; 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return retval; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define RUN_SILENT(check, func) RunSilent(&(check), &HeapLeakChecker::func) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum CheckType { SAME_HEAP, NO_LEAKS }; 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void VerifyLeaks(HeapLeakChecker* check, CheckType type, 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int leaked_bytes, int leaked_objects) { 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WipeStack(); // to help with can_create_leaks_reliably 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool no_leaks = 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type == NO_LEAKS ? RUN_SILENT(*check, BriefNoLeaks) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : RUN_SILENT(*check, BriefSameHeap); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (can_create_leaks_reliably) { 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // these might still fail occasionally, but it should be very rare 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(no_leaks, false); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(check->BytesLeaked(), leaked_bytes); 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(check->ObjectsLeaked(), leaked_objects); 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WARN_IF(no_leaks != false, 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Expected leaks not found: " 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Some liveness flood must be too optimistic"); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not deallocates 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerDeathSimple() { 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker check("death_simple"); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* foo = AllocHidden(100 * sizeof(int)); 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&foo); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar = AllocHidden(300); 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar); 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Leaking", foo); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Leaking", bar); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyLeaks(&check, NO_LEAKS, 300 + 100 * sizeof(int), 2); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&foo); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar); 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void MakeDeathLoop(void** arr1, void** arr2) { 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PreventHeapReclaiming(2 * sizeof(void*)); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void** a1 = new(initialized) void*[2]; 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void** a2 = new(initialized) void*[2]; 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) a1[1] = reinterpret_cast<void*>(a2); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) a2[1] = reinterpret_cast<void*>(a1); 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Hide(&a1); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Hide(&a2); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&a1); 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&a2); 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << "Made hidden loop at " << &a1 << " to " << arr1; 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *arr1 = a1; 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *arr2 = a2; 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not deallocates two objects linked together 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerDeathLoop() { 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker check("death_loop"); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* arr1; 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* arr2; 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunHidden(NewCallback(MakeDeathLoop, &arr1, &arr2)); 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&arr1); 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&arr2); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Leaking", arr1); 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Leaking", arr2); 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyLeaks(&check, NO_LEAKS, 4 * sizeof(void*), 2); 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&arr1); 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&arr2); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// deallocates more than allocates 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerDeathInverse() { 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar = AllocHidden(250 * sizeof(int)); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Pre leaking", bar); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker check("death_inverse"); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* foo = AllocHidden(100 * sizeof(int)); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&foo); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Leaking", foo); 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar); 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyLeaks(&check, SAME_HEAP, 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 100 * static_cast<int64>(sizeof(int)), 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1); 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&foo); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// deallocates more than allocates 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerDeathNoLeaks() { 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* foo = AllocHidden(100 * sizeof(int)); 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&foo); 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar = AllocHidden(250 * sizeof(int)); 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar); 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker check("death_noleaks"); 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar); 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(check.BriefNoLeaks(), true); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&foo); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// have less objecs 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerDeathCountLess() { 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar1 = AllocHidden(50 * sizeof(int)); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar1); 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar2 = AllocHidden(50 * sizeof(int)); 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar2); 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Pre leaking", bar1); 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Pre leaking", bar2); 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker check("death_count_less"); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* foo = AllocHidden(100 * sizeof(int)); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&foo); 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Leaking", foo); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar1); 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar2); 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyLeaks(&check, SAME_HEAP, 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 100 * sizeof(int), 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1); 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&foo); 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// have more objecs 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerDeathCountMore() { 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* foo = AllocHidden(100 * sizeof(int)); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&foo); 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Pre leaking", foo); 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker check("death_count_more"); 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar1 = AllocHidden(50 * sizeof(int)); 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar1); 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar2 = AllocHidden(50 * sizeof(int)); 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar2); 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Leaking", bar1); 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Leaking", bar2); 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&foo); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyLeaks(&check, SAME_HEAP, 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 100 * sizeof(int), 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2); 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar1); 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar2); 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHiddenPointer() { 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* foo = &i; 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HiddenPointer<void> p(foo); 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(foo, p.get()); 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Confirm pointer doesn't appear to contain a byte sequence 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that == the pointer. We don't really need to test that 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the xor trick itself works, as without it nothing in this 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // test suite would work. See the Hide/Unhide/*Hidden* set 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of helper methods. 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_NE(foo, *reinterpret_cast<void**>(&p)); 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// simple tests that deallocate what they allocated 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakChecker() { 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { HeapLeakChecker check("trivial"); 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int foo = 5; 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* p = &foo; 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&p); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(check.BriefSameHeap()); 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { HeapLeakChecker check("simple"); 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* foo = AllocHidden(100 * sizeof(int)); 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&foo); 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar = AllocHidden(200 * sizeof(int)); 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar); 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&foo); 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar); 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(check.BriefSameHeap()); 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// no false positives 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerNoFalsePositives() { 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { HeapLeakChecker check("trivial_p"); 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int foo = 5; 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* p = &foo; 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&p); 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(check.BriefSameHeap()); 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { HeapLeakChecker check("simple_p"); 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* foo = AllocHidden(100 * sizeof(int)); 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&foo); 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar = AllocHidden(200 * sizeof(int)); 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar); 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&foo); 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar); 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(check.SameHeap()); 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// test that we detect leaks when we have same total # of bytes and 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// objects, but different individual object sizes 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestLeakButTotalsMatch() { 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar1 = AllocHidden(240 * sizeof(int)); 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar1); 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar2 = AllocHidden(160 * sizeof(int)); 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar2); 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Pre leaking", bar1); 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Pre leaking", bar2); 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker check("trick"); 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* foo1 = AllocHidden(280 * sizeof(int)); 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&foo1); 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* foo2 = AllocHidden(120 * sizeof(int)); 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&foo2); 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Leaking", foo1); 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Leaking", foo2); 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar1); 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar2); 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // foo1 and foo2 leaked 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyLeaks(&check, NO_LEAKS, (280+120)*sizeof(int), 2); 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&foo1); 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&foo2); 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// no false negatives from pprof 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerDeathTrick() { 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar1 = AllocHidden(240 * sizeof(int)); 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar1); 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar2 = AllocHidden(160 * sizeof(int)); 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar2); 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker check("death_trick"); 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar1); 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar2); 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* foo1 = AllocHidden(280 * sizeof(int)); 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&foo1); 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* foo2 = AllocHidden(120 * sizeof(int)); 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&foo2); 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(maxim): use the above if we make pprof work in automated test runs 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!FLAGS_maybe_stripped) { 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(RUN_SILENT(check, SameHeap), false); 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pprof checking should catch the leak 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WARN_IF(RUN_SILENT(check, SameHeap) != false, 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "death_trick leak is not caught; " 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "we must be using a stripped binary"); 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&foo1); 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&foo2); 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// simple leak 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TransLeaks() { 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AllocHidden(1 * sizeof(char)); 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// range-based disabling using Disabler 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void ScopedDisabledLeaks() { 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::Disabler disabler; 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AllocHidden(3 * sizeof(int)); 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TransLeaks(); 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void)malloc(10); // Direct leak 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// have different disabled leaks 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void* RunDisabledLeaks(void* a) { 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedDisabledLeaks(); 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return a; 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// have different disabled leaks inside of a thread 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void ThreadDisabledLeaks() { 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_no_threads) return; 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_t tid; 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_attr_t attr; 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(pthread_attr_init(&attr), 0); 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(pthread_create(&tid, &attr, RunDisabledLeaks, NULL), 0); 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* res; 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(pthread_join(tid, &res), 0); 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// different disabled leaks (some in threads) 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerDisabling() { 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker check("disabling"); 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunDisabledLeaks(NULL); 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunDisabledLeaks(NULL); 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadDisabledLeaks(); 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunDisabledLeaks(NULL); 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadDisabledLeaks(); 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadDisabledLeaks(); 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(check.SameHeap()); 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef set<int> IntSet; 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int some_ints[] = { 1, 2, 3, 21, 22, 23, 24, 25 }; 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DoTestSTLAlloc() { 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IntSet* x = new(initialized) IntSet[1]; 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *x = IntSet(some_ints, some_ints + 6); 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < 1000; i++) { 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x->insert(i*3); 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete [] x; 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Check that normal STL usage does not result in a leak report. 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (In particular we test that there's no complex STL's own allocator 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// running on top of our allocator with hooks to heap profiler 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that can result in false leak report in this case.) 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestSTLAlloc() { 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker check("stl"); 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunHidden(NewCallback(DoTestSTLAlloc)); 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(check.BriefSameHeap(), true); 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DoTestSTLAllocInverse(IntSet** setx) { 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IntSet* x = new(initialized) IntSet[1]; 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *x = IntSet(some_ints, some_ints + 3); 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < 100; i++) { 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x->insert(i*2); 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Hide(&x); 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *setx = x; 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void FreeTestSTLAllocInverse(IntSet** setx) { 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IntSet* x = *setx; 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnHide(&x); 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete [] x; 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Check that normal leaked STL usage *does* result in a leak report. 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (In particular we test that there's no complex STL's own allocator 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// running on top of our allocator with hooks to heap profiler 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that can result in false absence of leak report in this case.) 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestSTLAllocInverse() { 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker check("death_inverse_stl"); 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IntSet* x; 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunHidden(NewCallback(DoTestSTLAllocInverse, &x)); 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Leaking", x); 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (can_create_leaks_reliably) { 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WipeStack(); // to help with can_create_leaks_reliably 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // these might still fail occasionally, but it should be very rare 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(RUN_SILENT(check, BriefNoLeaks), false); 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_GE(check.BytesLeaked(), 100 * sizeof(int)); 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_GE(check.ObjectsLeaked(), 100); 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // assumes set<>s are represented by some kind of binary tree 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // or something else allocating >=1 heap object per set object 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WARN_IF(RUN_SILENT(check, BriefNoLeaks) != false, 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Expected leaks not found: " 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Some liveness flood must be too optimistic"); 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunHidden(NewCallback(FreeTestSTLAllocInverse, &x)); 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<class Alloc> 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DirectTestSTLAlloc(Alloc allocator, const char* name) { 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker check((string("direct_stl-") + name).c_str()); 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kSize = 1000; 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typename Alloc::pointer ptrs[kSize]; 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kSize; ++i) { 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typename Alloc::pointer p = allocator.allocate(i*3+1); 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::IgnoreObject(p); 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This will crash if p is not known to heap profiler: 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (i.e. STL's "allocator" does not have a direct hook to heap profiler) 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::UnIgnoreObject(p); 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptrs[i] = p; 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kSize; ++i) { 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) allocator.deallocate(ptrs[i], i*3+1); 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptrs[i] = NULL; 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(check.BriefSameHeap()); // just in case 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct group* grp = NULL; 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kKeys = 50; 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static pthread_key_t key[kKeys]; 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void KeyFree(void* ptr) { 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete [] reinterpret_cast<char*>(ptr); 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool key_init_has_run = false; 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void KeyInit() { 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kKeys; ++i) { 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(pthread_key_create(&key[i], KeyFree), 0); 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << "pthread key " << i << " : " << key[i]; 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_init_has_run = true; // needed for a sanity-check 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// force various C library static and thread-specific allocations 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestLibCAllocate() { 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(key_init_has_run); 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kKeys; ++i) { 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* p = pthread_getspecific(key[i]); 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NULL == p) { 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == 0) { 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test-logging inside threads which (potentially) creates and uses 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread-local data inside standard C++ library: 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Adding pthread-specifics for thread " << pthread_self() 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " pid " << getpid(); 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p = new(initialized) char[77 + i]; 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << "pthread specific " << i << " : " << p; 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_setspecific(key[i], p); 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strerror(errno); 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const time_t now = time(NULL); 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctime(&now); 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_EXECINFO_H 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *stack[1]; 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backtrace(stack, 1); 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_GRP_H 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gid_t gid = getgid(); 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getgrgid(gid); 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (grp == NULL) grp = getgrent(); // a race condition here is okay 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getgrnam(grp->gr_name); 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_PWD_H 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getpwuid(geteuid()); 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Continuous random heap memory activity to try to disrupt heap checking. 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void* HeapBusyThreadBody(void* a) { 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int thread_num = reinterpret_cast<intptr_t>(a); 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "A new HeapBusyThread " << thread_num; 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestLibCAllocate(); 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int user = 0; 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try to hide ptr from heap checker in a CPU register: 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Here we are just making a best effort to put the only pointer 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to a heap object into a thread register to test 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the thread-register finding machinery in the heap checker. 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__i386__) && defined(__GNUC__) 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) register int** ptr asm("esi"); 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(__x86_64__) && defined(__GNUC__) 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) register int** ptr asm("r15"); 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) register int** ptr; 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr = NULL; 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef set<int> Set; 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Set s1; 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (1) { 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TestLibCAllocate() calls libc functions that don't work so well 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // after main() has exited. So we just don't do the test then. 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!g_have_exited_main) 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestLibCAllocate(); 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ptr == NULL) { 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr = new(initialized) int*[1]; 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ptr = new(initialized) int[1]; 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set<int>* s2 = new(initialized) set<int>[1]; 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s1.insert(random()); 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s2->insert(*s1.begin()); 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user += *s2->begin(); 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) **ptr += user; 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (random() % 51 == 0) { 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s1.clear(); 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (random() % 2 == 0) { 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s1.~Set(); 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new(&s1) Set; 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(3) << pthread_self() << " (" << getpid() << "): in wait: " 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ptr << ", " << *ptr << "; " << s1.size(); 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << pthread_self() << " (" << getpid() << "): in wait, ptr = " 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << reinterpret_cast<void*>( 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<uintptr_t>(ptr) ^ kHideMask) 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "^" << reinterpret_cast<void*>(kHideMask); 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_test_register_leak && thread_num % 5 == 0) { 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Hide the register "ptr" value with an xor mask. 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If one provides --test_register_leak flag, the test should 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (with very high probability) crash on some leak check 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with a leak report (of some x * sizeof(int) + y * sizeof(int*) bytes) 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pointing at the two lines above in this function 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with "new(initialized) int" in them as the allocators 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of the leaked objects. 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CAVEAT: We can't really prevent a compiler to save some 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // temporary values of "ptr" on the stack and thus let us find 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the heap objects not via the register. 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Hence it's normal if for certain compilers or optimization modes 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // --test_register_leak does not cause a leak crash of the above form 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (this happens e.g. for gcc 4.0.1 in opt mode). 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr = reinterpret_cast<int **>( 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<uintptr_t>(ptr) ^ kHideMask); 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // busy loop to get the thread interrupted at: 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 1; i < 10000000; ++i) user += (1 + user * user * 5) / i; 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr = reinterpret_cast<int **>( 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<uintptr_t>(ptr) ^ kHideMask); 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) poll(NULL, 0, random() % 100); 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << pthread_self() << ": continuing"; 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (random() % 3 == 0) { 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete [] *ptr; 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete [] ptr; 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr = NULL; 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete [] s2; 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return a; 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void RunHeapBusyThreads() { 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KeyInit(); 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!FLAGS_interfering_threads || FLAGS_no_threads) return; 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int n = 17; // make many threads 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_t tid; 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_attr_t attr; 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(pthread_attr_init(&attr), 0); 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // make them and let them run 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < n; ++i) { 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Creating extra thread " << i + 1; 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(pthread_create(&tid, &attr, HeapBusyThreadBody, 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<void*>(i)) == 0); 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ========================================================================= // 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This code section is to test that objects that are reachable from global 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// variables are not reported as leaks 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as well as that (Un)IgnoreObject work for such objects fine. 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An object making functions: 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// returns a "weird" pointer to a new object for which 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it's worth checking that the object is reachable via that pointer. 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef void* (*ObjMakerFunc)(); 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static list<ObjMakerFunc> obj_makers; // list of registered object makers 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper macro to register an object making function 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 'name' is an identifier of this object maker, 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 'body' is its function body that must declare 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pointer 'p' to the nex object to return. 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Usage example: 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// REGISTER_OBJ_MAKER(trivial, int* p = new(initialized) int;) 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define REGISTER_OBJ_MAKER(name, body) \ 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* ObjMaker_##name##_() { \ 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Obj making " << #name; \ 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) body; \ 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return p; \ 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } \ 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static ObjMakerRegistrar maker_reg_##name##__(&ObjMaker_##name##_); 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// helper class for REGISTER_OBJ_MAKER 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ObjMakerRegistrar { 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ObjMakerRegistrar(ObjMakerFunc obj_maker) { obj_makers.push_back(obj_maker); } 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// List of the objects/pointers made with all the obj_makers 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to test reachability via global data pointers during leak checks. 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static list<void*>* live_objects = new list<void*>; 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pointer so that it does not get destructed on exit 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Exerciser for one ObjMakerFunc. 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestPointerReach(ObjMakerFunc obj_maker) { 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::IgnoreObject(obj_maker()); // test IgnoreObject 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* obj = obj_maker(); 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::IgnoreObject(obj); 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::UnIgnoreObject(obj); // test UnIgnoreObject 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::IgnoreObject(obj); // not to need deletion for obj 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_objects->push_back(obj_maker()); // test reachability at leak check 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test all ObjMakerFunc registred via REGISTER_OBJ_MAKER. 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestObjMakers() { 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (list<ObjMakerFunc>::const_iterator i = obj_makers.begin(); 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != obj_makers.end(); ++i) { 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestPointerReach(*i); 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestPointerReach(*i); // a couple more times would not hurt 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestPointerReach(*i); 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A dummy class to mimic allocation behavior of string-s. 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<class T> 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Array { 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Array() { 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size = 3 + random() % 30; 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr = new(initialized) T[size]; 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~Array() { delete [] ptr; } 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Array(const Array& x) { 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size = x.size; 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr = new(initialized) T[size]; 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < size; ++i) { 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr[i] = x.ptr[i]; 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void operator=(const Array& x) { 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete [] ptr; 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size = x.size; 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr = new(initialized) T[size]; 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < size; ++i) { 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr[i] = x.ptr[i]; 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void append(const Array& x) { 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) T* p = new(initialized) T[size + x.size]; 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < size; ++i) { 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p[i] = ptr[i]; 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < x.size; ++i) { 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p[size+i] = x.ptr[i]; 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size += x.size; 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete [] ptr; 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr = p; 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size; 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) T* ptr; 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to test pointers to objects, built-in arrays, string, etc: 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(plain, int* p = new(initialized) int;) 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(int_array_1, int* p = new(initialized) int[1];) 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(int_array, int* p = new(initialized) int[10];) 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(string, Array<char>* p = new(initialized) Array<char>();) 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(string_array, 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Array<char>* p = new(initialized) Array<char>[5];) 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(char_array, char* p = new(initialized) char[5];) 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(appended_string, 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Array<char>* p = new Array<char>(); 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->append(Array<char>()); 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)) 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(plain_ptr, int** p = new(initialized) int*;) 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(linking_ptr, 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int** p = new(initialized) int*; 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p = new(initialized) int; 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)) 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// small objects: 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(0_sized, void* p = malloc(0);) // 0-sized object (important) 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(1_sized, void* p = malloc(1);) 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(2_sized, void* p = malloc(2);) 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(3_sized, void* p = malloc(3);) 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(4_sized, void* p = malloc(4);) 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int set_data[] = { 1, 2, 3, 4, 5, 6, 7, 21, 22, 23, 24, 25, 26, 27 }; 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static set<int> live_leak_set(set_data, set_data+7); 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const set<int> live_leak_const_set(set_data, set_data+14); 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(set, 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set<int>* p = new(initialized) set<int>(set_data, set_data + 13); 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)) 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ClassA { 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit ClassA(int a) : ptr(NULL) { } 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mutable char* ptr; 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ClassA live_leak_mutable(1); 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<class C> 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TClass { 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit TClass(int a) : ptr(NULL) { } 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mutable C val; 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mutable C* ptr; 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const TClass<Array<char> > live_leak_templ_mutable(1); 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ClassB { 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClassB() { } 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char b[7]; 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void f() { } 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~ClassB() { } 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ClassB2 { 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClassB2() { } 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char b2[11]; 11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void f2() { } 11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~ClassB2() { } 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ClassD1 : public ClassB { 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char d1[15]; 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void f() { } 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ClassD2 : public ClassB2 { 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char d2[19]; 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void f2() { } 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ClassD : public ClassD1, public ClassD2 { 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char d[3]; 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void f() { } 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void f2() { } 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to test pointers to objects of base subclasses: 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(B, ClassB* p = new(initialized) ClassB;) 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(D1, ClassD1* p = new(initialized) ClassD1;) 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(D2, ClassD2* p = new(initialized) ClassD2;) 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(D, ClassD* p = new(initialized) ClassD;) 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(D1_as_B, ClassB* p = new(initialized) ClassD1;) 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(D2_as_B2, ClassB2* p = new(initialized) ClassD2;) 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(D_as_B, ClassB* p = new(initialized) ClassD;) 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(D_as_D1, ClassD1* p = new(initialized) ClassD;) 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// inside-object pointers: 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(D_as_B2, ClassB2* p = new(initialized) ClassD;) 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(D_as_D2, ClassD2* p = new(initialized) ClassD;) 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class InterfaceA { 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void A() = 0; 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~InterfaceA() { } 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InterfaceA() { } 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class InterfaceB { 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void B() = 0; 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~InterfaceB() { } 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InterfaceB() { } 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class InterfaceC : public InterfaceA { 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void C() = 0; 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~InterfaceC() { } 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InterfaceC() { } 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ClassMltD1 : public ClassB, public InterfaceB, public InterfaceC { 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char d1[11]; 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void f() { } 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void A() { } 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void B() { } 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void C() { } 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ClassMltD2 : public InterfaceA, public InterfaceB, public ClassB { 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char d2[15]; 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void f() { } 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void A() { } 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void B() { } 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to specifically test heap reachability under 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// inerface-only multiple inheritance (some use inside-object pointers): 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(MltD1, ClassMltD1* p = new(initialized) ClassMltD1;) 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(MltD1_as_B, ClassB* p = new(initialized) ClassMltD1;) 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(MltD1_as_IA, InterfaceA* p = new(initialized) ClassMltD1;) 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(MltD1_as_IB, InterfaceB* p = new(initialized) ClassMltD1;) 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(MltD1_as_IC, InterfaceC* p = new(initialized) ClassMltD1;) 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(MltD2, ClassMltD2* p = new(initialized) ClassMltD2;) 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(MltD2_as_B, ClassB* p = new(initialized) ClassMltD2;) 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(MltD2_as_IA, InterfaceA* p = new(initialized) ClassMltD2;) 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(MltD2_as_IB, InterfaceB* p = new(initialized) ClassMltD2;) 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to mimic UnicodeString defined in third_party/icu, 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which store a platform-independent-sized refcount in the first 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// few bytes and keeps a pointer pointing behind the refcount. 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(unicode_string, 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* p = new char[sizeof(uint32) * 10]; 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p += sizeof(uint32); 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)) 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// similar, but for platform-dependent-sized refcount 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(ref_counted, 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* p = new char[sizeof(int) * 20]; 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p += sizeof(int); 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)) 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Nesting { 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct Inner { 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Nesting* parent; 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Inner(Nesting* p) : parent(p) {} 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Inner i0; 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char n1[5]; 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Inner i1; 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char n2[11]; 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Inner i2; 12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char n3[27]; 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Inner i3; 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Nesting() : i0(this), i1(this), i2(this), i3(this) {} 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to test inside-object pointers pointing at objects nested into heap objects: 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(nesting_i0, Nesting::Inner* p = &((new Nesting())->i0);) 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(nesting_i1, Nesting::Inner* p = &((new Nesting())->i1);) 12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(nesting_i2, Nesting::Inner* p = &((new Nesting())->i2);) 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(nesting_i3, Nesting::Inner* p = &((new Nesting())->i3);) 12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// allocate many objects reachable from global data 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerLiveness() { 12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_leak_mutable.ptr = new(initialized) char[77]; 12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_leak_templ_mutable.ptr = new(initialized) Array<char>(); 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_leak_templ_mutable.val = Array<char>(); 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestObjMakers(); 12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ========================================================================= // 12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Get address (PC value) following the mmap call into addr_after_mmap_call 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void* Mmapper(uintptr_t* addr_after_mmap_call) { 12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* r = mmap(NULL, 100, PROT_READ|PROT_WRITE, 12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get current PC value into addr_after_mmap_call 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* stack[1]; 12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(GetStackTrace(stack, 1, 0), 1); 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *addr_after_mmap_call = reinterpret_cast<uintptr_t>(stack[0]); 12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sleep(0); // undo -foptimize-sibling-calls 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return r; 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to trick complier into preventing inlining 12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void* (*mmapper_addr)(uintptr_t* addr) = &Mmapper; 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(maxim): copy/move this to memory_region_map_unittest 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(maxim): expand this test to include mmap64, mremap and sbrk calls. 12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void VerifyMemoryRegionMapStackGet() { 12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t caller_addr_limit; 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* addr = (*mmapper_addr)(&caller_addr_limit); 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t caller = 0; 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { MemoryRegionMap::LockHolder l; 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (MemoryRegionMap::RegionIterator 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i = MemoryRegionMap::BeginRegionLocked(); 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != MemoryRegionMap::EndRegionLocked(); ++i) { 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i->start_addr == reinterpret_cast<uintptr_t>(addr)) { 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(caller, 0); 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) caller = i->caller(); 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // caller must point into Mmapper function: 12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(reinterpret_cast<uintptr_t>(mmapper_addr) <= caller && 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) caller < caller_addr_limit)) { 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOGF << std::hex << "0x" << caller 12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " does not seem to point into code of function Mmapper at " 12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "0x" << reinterpret_cast<uintptr_t>(mmapper_addr) 12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "! Stack frame collection must be off in MemoryRegionMap!"; 12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(FATAL, "\n"); 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) munmap(addr, 100); 12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void* Mallocer(uintptr_t* addr_after_malloc_call) { 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* r = malloc(100); 12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sleep(0); // undo -foptimize-sibling-calls 12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get current PC value into addr_after_malloc_call 13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* stack[1]; 13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(GetStackTrace(stack, 1, 0), 1); 13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *addr_after_malloc_call = reinterpret_cast<uintptr_t>(stack[0]); 13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return r; 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to trick complier into preventing inlining 13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void* (*mallocer_addr)(uintptr_t* addr) = &Mallocer; 13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// non-static for friendship with HeapProfiler 13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(maxim): expand this test to include 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// realloc, calloc, memalign, valloc, pvalloc, new, and new[]. 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern void VerifyHeapProfileTableStackGet() { 13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t caller_addr_limit; 13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* addr = (*mallocer_addr)(&caller_addr_limit); 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t caller = 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<uintptr_t>(HeapLeakChecker::GetAllocCaller(addr)); 13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // caller must point into Mallocer function: 13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(reinterpret_cast<uintptr_t>(mallocer_addr) <= caller && 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) caller < caller_addr_limit)) { 13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOGF << std::hex << "0x" << caller 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " does not seem to point into code of function Mallocer at " 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "0x" << reinterpret_cast<uintptr_t>(mallocer_addr) 13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "! Stack frame collection must be off in heap profiler!"; 13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(FATAL, "\n"); 13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(addr); 13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ========================================================================= // 13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void MakeALeak(void** arr) { 13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PreventHeapReclaiming(10 * sizeof(int)); 13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* a = new(initialized) int[10]; 13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Hide(&a); 13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *arr = a; 13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper to do 'return 0;' inside main(): insted we do 'return Pass();' 13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int Pass() { 13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(stdout, "PASS\n"); 13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_have_exited_main = true; 13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int main(int argc, char** argv) { 13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) run_hidden_ptr = DoRunHidden; 13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wipe_stack_ptr = DoWipeStack; 13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!HeapLeakChecker::IsActive()) { 13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(FLAGS_heap_check, ""); 13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING, "HeapLeakChecker got turned off; we won't test much..."); 13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyMemoryRegionMapStackGet(); 13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyHeapProfileTableStackGet(); 13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KeyInit(); 13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // glibc 2.4, on x86_64 at least, has a lock-ordering bug, which 13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // means deadlock is possible when one thread calls dl_open at the 13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // same time another thread is calling dl_iterate_phdr. libunwind 13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // calls dl_iterate_phdr, and TestLibCAllocate calls dl_open (or the 13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // various syscalls in it do), at least the first time it's run. 13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To avoid the deadlock, we run TestLibCAllocate once before getting 13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // multi-threaded. 13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(csilvers): once libc is fixed, or libunwind can work around it, 13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // get rid of this early call. We *want* our test to 13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // find potential problems like this one! 13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestLibCAllocate(); 13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_interfering_threads) { 13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunHeapBusyThreads(); // add interference early 13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestLibCAllocate(); 13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOGF << "In main(): heap_check=" << FLAGS_heap_check << endl; 13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(HeapLeakChecker::NoGlobalLeaks()); // so far, so good 13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_test_leak) { 13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* arr; 13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunHidden(NewCallback(MakeALeak, &arr)); 13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&arr); 13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Leaking", arr); 13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_test_cancel_global_check) { 13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::CancelGlobalCheck(); 13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify we can call NoGlobalLeaks repeatedly without deadlocking 13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::NoGlobalLeaks(); 13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::NoGlobalLeaks(); 13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Pass(); 13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // whole-program leak-check should (with very high probability) 13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // catch the leak of arr (10 * sizeof(int) bytes) 13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (when !FLAGS_test_cancel_global_check) 13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_test_loop_leak) { 13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* arr1; 13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* arr2; 14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunHidden(NewCallback(MakeDeathLoop, &arr1, &arr2)); 14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&arr1); 14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&arr2); 14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Loop leaking", arr1); 14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Loop leaking", arr2); 14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_test_cancel_global_check) { 14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::CancelGlobalCheck(); 14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify we can call NoGlobalLeaks repeatedly without deadlocking 14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::NoGlobalLeaks(); 14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::NoGlobalLeaks(); 14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Pass(); 14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // whole-program leak-check should (with very high probability) 14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // catch the leak of arr1 and arr2 (4 * sizeof(void*) bytes) 14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (when !FLAGS_test_cancel_global_check) 14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_test_register_leak) { 14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // make us fail only where the .sh test expects: 14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < 100; ++i) { // give it some time to crash 14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(HeapLeakChecker::NoGlobalLeaks()); 14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Pass(); 14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestHeapLeakCheckerLiveness(); 14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker heap_check("all"); 14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestHiddenPointer(); 14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestHeapLeakChecker(); 14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestLeakButTotalsMatch(); 14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestHeapLeakCheckerDeathSimple(); 14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestHeapLeakCheckerDeathLoop(); 14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestHeapLeakCheckerDeathInverse(); 14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestHeapLeakCheckerDeathNoLeaks(); 14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestHeapLeakCheckerDeathCountLess(); 14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestHeapLeakCheckerDeathCountMore(); 14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestHeapLeakCheckerDeathTrick(); 14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(HeapLeakChecker::NoGlobalLeaks()); // so far, so good 14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestHeapLeakCheckerNoFalsePositives(); 14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestHeapLeakCheckerDisabling(); 14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestSTLAlloc(); 14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestSTLAllocInverse(); 14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test that various STL allocators work. Some of these are redundant, but 14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we don't know how STL might change in the future. For example, 14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://wiki/Main/StringNeStdString. 14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DTSL(a) { DirectTestSTLAlloc(a, #a); \ 14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); } 14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DTSL(std::allocator<char>()); 14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DTSL(std::allocator<int>()); 14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DTSL(std::string().get_allocator()); 14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DTSL(string().get_allocator()); 14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DTSL(vector<int>().get_allocator()); 14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DTSL(vector<double>().get_allocator()); 14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DTSL(vector<vector<int> >().get_allocator()); 14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DTSL(vector<string>().get_allocator()); 14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DTSL((map<string, string>().get_allocator())); 14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DTSL((map<string, int>().get_allocator())); 14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DTSL(set<char>().get_allocator()); 14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef DTSL 14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestLibCAllocate(); 14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(HeapLeakChecker::NoGlobalLeaks()); // so far, so good 14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!FLAGS_maybe_stripped) { 14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(heap_check.SameHeap()); 14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WARN_IF(heap_check.SameHeap() != true, 14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "overall leaks are caught; we must be using a stripped binary"); 14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(HeapLeakChecker::NoGlobalLeaks()); // so far, so good 15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Pass(); 15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1504