#define __STDC_FORMAT_MACROS #include <inttypes.h> #include <stdio.h> #include <unistd.h> #include <stdint.h> #include <stdlib.h> #include <string> #include <sstream> #include "../memcheck.h" // Derived from test provided by Timur Iskhodzhanov (bug 280271) class MyClass { char m1; int m2; public: ~MyClass() { fprintf(stderr, "destruct MyClass\n"); } }; // Two hierarchies using MI, one with no fields, // the other one with some data. struct Ae { virtual ~Ae() { fprintf(stderr, "destruct Ae\n"); } }; struct Be { virtual ~Be() { fprintf(stderr, "destruct Be\n"); } }; struct Ce : public Ae, public Be { virtual ~Ce() { fprintf(stderr, "destruct Ce\n"); } }; struct A { char a; A() { a = 'a'; } virtual ~A() { fprintf(stderr, "destruct A\n"); } }; struct B { char b; B() { b = 'b'; } virtual ~B() { fprintf(stderr, "destruct B\n"); } }; struct C : public A, public B { char c; C() { c = 'c'; } virtual ~C() { fprintf(stderr, "destruct C\n"); } }; void* wrap64_malloc(int size) { uint64_t *p = (uint64_t*)malloc(size + 8); *p = size; ++p; return p; } void wrap64_free(void *p) { uint64_t *p2 = (uint64_t*)p; if (p2 == NULL) return; --p2; free(p2); } std::string str; std::string str2; MyClass *ptr; MyClass *ptr2; Be *ptrBCe; Ae *ptrACe; B *ptrBC; A *ptrAC; void* ptr64; char who_points_at_cmd[100]; void doit(void) { str = "Valgrind"; // interior ptr. str2 = str; ptr = new MyClass[3]; // interior ptr. ptr64 = wrap64_malloc(23); // prepare the who_points_at cmd we will run. // Do it here to avoid having ptr or its exterior ptr kept in a register. sprintf(who_points_at_cmd, "who_points_at %#" PRIxPTR " 20", (uintptr_t) (char*)ptr - sizeof(void*)); ptr2 = new MyClass[0]; // "interior but exterior ptr". // ptr2 points after the chunk, is wrongly considered by memcheck as definitely leaked. ptrBCe = new Ce; // interior ptr. ptrACe = new Ce; // not an interior pointer. ptrBC = new C; // interior ptr. ptrAC = new C; // not an interior pointer. str2 += " rocks (str2)\n"; // interior ptr. } int main() { doit(); (void) VALGRIND_MONITOR_COMMAND("v.set log_output"); fprintf(stderr, "VALGRIND_DO_LEAK_CHECK\n"); VALGRIND_DO_LEAK_CHECK; // All possible leaks should be detected, giving only reachable data. // Check individually each heuristic fprintf(stderr, "leak_check summary heuristics multipleinheritance\n"); (void) VALGRIND_MONITOR_COMMAND("leak_check summary heuristics multipleinheritance"); fprintf(stderr, "leak_check summary any heuristics newarray\n"); (void) VALGRIND_MONITOR_COMMAND("leak_check summary heuristics newarray"); fprintf(stderr, "leak_check summary heuristics length64\n"); (void) VALGRIND_MONITOR_COMMAND("leak_check summary heuristics length64"); fprintf(stderr, "leak_check summary heuristics stdstring\n"); (void) VALGRIND_MONITOR_COMMAND("leak_check summary heuristics stdstring"); // check all and none fprintf(stderr, "leak_check summary heuristics multipleinheritance,newarray,stdstring,length64\n"); (void) VALGRIND_MONITOR_COMMAND("leak_check summary heuristics multipleinheritance,newarray,stdstring,length64"); fprintf(stderr, "leak_check summary heuristics all\n"); (void) VALGRIND_MONITOR_COMMAND("leak_check summary heuristics all"); fprintf(stderr, "leak_check summary heuristics none\n"); (void) VALGRIND_MONITOR_COMMAND("leak_check summary heuristics none"); // Test the who_points_at when the block is pointed to with an interior ptr. (void) VALGRIND_MONITOR_COMMAND(who_points_at_cmd); delete [] ptr; delete [] ptr2; delete ptrBCe; delete ptrACe; delete ptrBC; delete ptrAC; wrap64_free(ptr64); fprintf(stderr, "Finished!\n"); return 0; }