Challenge 3: A Class Following Neither Rule — The Double-Free, Demonstrated — Possible Solution ==================================================================== #include class Leaky { public: int *data; Leaky(int value) { data = new int(value); } ~Leaky() { delete data; std::cout << "Destructor ran, deleted data" << std::endl; } // deliberately NO copy constructor, NO copy assignment operator written }; int main() { Leaky a(42); Leaky b = a; // uses the COMPILER'S default (shallow) copy constructor return 0; } // both a and b are destroyed here, in reverse order of construction Output (representative -- the second delete is undefined behavior, so the exact symptom is not guaranteed): Destructor ran, deleted data Destructor ran, deleted data free(): double free detected in tcache 2 Aborted (core dumped) What goes wrong: Leaky writes its own destructor (satisfying part of the Rule of Three) but does NOT write a copy constructor or copy assignment operator -- violating the Rule of Three's own requirement to write all three together, and also not following the Rule of Zero (data is a raw pointer, not an RAII wrapper). Since no copy constructor was written by hand, the COMPILER generates a default one, which simply copies the data member's VALUE -- the raw pointer address itself -- into b.data, without allocating any new memory. After the copy, a.data and b.data are two separate pointer VARIABLES holding the IDENTICAL address, each believing itself the sole owner of that memory. When main ends, both a and b are destroyed (in reverse construction order): a's destructor calls delete on the shared address first, which succeeds and genuinely frees it. b's destructor then calls delete on the SAME address a second time -- exactly a double-free, per c2-3's own bug catalog -- undefined behavior, commonly manifesting as a crash (as shown above) but not guaranteed to. WHY THIS WORKS AS AN ANSWER ------------------------------ This constructs a class that genuinely violates BOTH the Rule of Three (destructor without the matching copy operations) and the Rule of Zero (a raw pointer member instead of an RAII wrapper), traces the compiler-generated shallow copy precisely (same address, two "owners"), and correctly identifies the resulting bug as a double-free -- naming it via c2-3's own established vocabulary rather than a vague "something breaks."