62 Intermediate The Hundred
Two Owners, One Corpse
two owners who never met
#include <iostream>
#include <memory>
int main() {
int* raw = new int(42);
std::shared_ptr<int> a(raw); // a manages the int
std::shared_ptr<int> b(raw); // b helps out... right?
std::cout << "a sees " << *a << " (use_count " << a.use_count() << ")" << std::endl;
std::cout << "b sees " << *b << " (use_count " << b.use_count() << ")" << std::endl;
std::cout << "leaving main..." << std::endl;
}
Run it. What does it print?
Answer
Both counts are 1, not 2 — and then it crashes. Typical output (GCC 11 / glibc on x86-64 Linux):
Why¶
A shared_ptr constructed from a raw pointer doesn't join existing ownership — it
founds it, allocating a brand-new control block with the count at 1. So a and b
have never heard of each other; the use_count 1 printed twice is the tell. When the
scope ends, each conscientiously deletes "its" int, and the second delete is
undefined behavior — here glibc catches it and aborts, but it could just as well
corrupt the heap silently or even appear to work. -Wall -Wextra says nothing; the
code is perfectly legal to compile.
The fix¶
Establish ownership once, then copy the smart pointer — copies share one control block:
The same trap fires when a member function wraps this in a fresh shared_ptr; the
cure there is std::enable_shared_from_this.
Takeaway: ownership is established exactly once — after that, copy the smart pointer, never the raw one.
Try it: g++ -std=c++17 main.cpp -o demo && ./demo