<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rui-Tech</title>
    <description>The latest articles on DEV Community by Rui-Tech (@legacycpp).</description>
    <link>https://dev.to/legacycpp</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3830024%2Ff4f48e4a-2672-44a3-8ee0-76063145b056.png</url>
      <title>DEV Community: Rui-Tech</title>
      <link>https://dev.to/legacycpp</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/legacycpp"/>
    <language>en</language>
    <item>
      <title>Debugging Legacy C++ Crashes: Core Dumps, Symbols, addr2line, and GDB Explained</title>
      <dc:creator>Rui-Tech</dc:creator>
      <pubDate>Sun, 26 Apr 2026 16:30:27 +0000</pubDate>
      <link>https://dev.to/legacycpp/debugging-legacy-c-crashes-core-dumps-symbols-addr2line-and-gdb-explained-33fh</link>
      <guid>https://dev.to/legacycpp/debugging-legacy-c-crashes-core-dumps-symbols-addr2line-and-gdb-explained-33fh</guid>
      <description>&lt;p&gt;You're on call. A production C++ service just crashed — no logs, no stack trace, just a dead process and maybe a core file.&lt;/p&gt;

&lt;p&gt;This guide gives you a &lt;strong&gt;clear, repeatable workflow&lt;/strong&gt; to diagnose any crash, even when you're missing debug symbols or working with a stripped legacy binary. Whether you have a core file, a symbol file, an unstripped build, or nothing at all, you will always know the next step.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;Debugging crashes in legacy C++ systems is notoriously difficult because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deployments often strip symbols&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Core dumps are disabled in production&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build IDs don’t match&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ASLR shifts memory layouts&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frame pointers are omitted&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Systemd overrides &lt;code&gt;ulimit&lt;/code&gt; settings&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This workflow eliminates guesswork and gives you a deterministic path from &lt;em&gt;crash&lt;/em&gt; to &lt;em&gt;root cause&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Crash Debugging Decision Map
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CRASH
  |
  v
HAVE CORE FILE?
  |-- No --&amp;gt; Enable cores (Path B) → Reproduce crash
  |
  |-- Yes (Path A)
        |
        v
   HAVE DEBUG SYMBOLS?
        |-- Yes --&amp;gt; Debug now (A4)
        |
        |-- No
              |
              v
        HAVE SYMBOL FILE?
              |-- Yes --&amp;gt; Load with -s (A6)
              |
              |-- No
                    |
                    v
        CAN REPRODUCE WITH SYMBOLS?
              |-- Yes --&amp;gt; Rebuild with -g (A7)
              |
              |-- No
                    |
                    v
        HAVE ORIGINAL BUILD?
              |-- Yes --&amp;gt; Map addresses (A8)
              |
              |-- No --&amp;gt; Fallback analysis (A9)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Path A — You Have a Core File
&lt;/h2&gt;

&lt;h3&gt;
  
  
  A1 — Locate the Core File
&lt;/h3&gt;

&lt;p&gt;Common locations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt; core&lt;span class="k"&gt;*&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt; /var/core/
find / &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"core*"&lt;/span&gt; &lt;span class="nt"&gt;-type&lt;/span&gt; f 2&amp;gt;/dev/null
&lt;span class="nb"&gt;cat&lt;/span&gt; /proc/sys/kernel/core_pattern
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you find a core file, continue to &lt;strong&gt;A2&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
If not, jump to &lt;strong&gt;Path B&lt;/strong&gt;.&lt;/p&gt;


&lt;h3&gt;
  
  
  A2 — Identify Which Binary Produced the Core
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;file core
gdb &lt;span class="nt"&gt;-c&lt;/span&gt; core &lt;span class="nt"&gt;-batch&lt;/span&gt; &lt;span class="nt"&gt;-ex&lt;/span&gt; &lt;span class="s2"&gt;"info files"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Confirm that the core file belongs to the binary you intend to debug (path, build, version).&lt;/p&gt;


&lt;h3&gt;
  
  
  A3 — Check Whether the Binary Has Debug Symbols
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;file ./myapp
nm ./myapp | &lt;span class="nb"&gt;head&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;If the binary is &lt;strong&gt;not stripped&lt;/strong&gt; and you see symbol names → go to &lt;strong&gt;A4&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;If it is &lt;strong&gt;stripped&lt;/strong&gt; → go to &lt;strong&gt;A5&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  A4 — Debugging With Symbols (Best Case)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gdb ./myapp core
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Useful GDB commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bt full
info threads
thread apply all bt
frame 0
info locals
print var
list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point you usually have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The crashing function and line
&lt;/li&gt;
&lt;li&gt;The call stack
&lt;/li&gt;
&lt;li&gt;Local variables and arguments
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  A5 — Binary Is Stripped: Find the Symbol File
&lt;/h3&gt;

&lt;p&gt;In many production setups, the deployed binary is stripped, but symbol files are archived separately.&lt;/p&gt;

&lt;h4&gt;
  
  
  A5.1 — Extract Build ID
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;readelf &lt;span class="nt"&gt;-n&lt;/span&gt; ./myapp | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"Build ID"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll get something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Build ID: 1234567890abcdef...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  A5.2 — Locate Matching Symbol File
&lt;/h4&gt;

&lt;p&gt;Search your symbol store (example path):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find /symbols &lt;span class="nt"&gt;-type&lt;/span&gt; f &lt;span class="nt"&gt;-exec&lt;/span&gt; &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="s2"&gt;"1234567890abcdef"&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If you find a matching symbol file → go to &lt;strong&gt;A6&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;If not → go to &lt;strong&gt;A7&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  A6 — Debug Using Separate Symbol Files
&lt;/h3&gt;

&lt;p&gt;If your symbol file is &lt;code&gt;myapp.dbg&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gdb &lt;span class="nt"&gt;-s&lt;/span&gt; myapp.dbg &lt;span class="nt"&gt;-e&lt;/span&gt; ./myapp &lt;span class="nt"&gt;-c&lt;/span&gt; core
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or recombine into a single unstripped binary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;eu-unstrip ./myapp myapp.dbg &lt;span class="nt"&gt;-o&lt;/span&gt; myapp.full
gdb ./myapp.full core
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can use the same commands as in &lt;strong&gt;A4&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  A7 — No Symbol File: Reproduce With Debug Build
&lt;/h3&gt;

&lt;p&gt;If you can rebuild and reproduce the crash:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;g++ &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;-O0&lt;/span&gt; &lt;span class="nt"&gt;-fno-omit-frame-pointer&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; myapp_debug ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the debug build under the same conditions until it crashes and generates a new core file. Then debug that core with full symbols as in &lt;strong&gt;A4&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you &lt;strong&gt;cannot&lt;/strong&gt; reproduce the crash (e.g., one‑off production incident), continue with &lt;strong&gt;A8&lt;/strong&gt; or &lt;strong&gt;A9&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  A8 — Map Raw Addresses Using an Unstripped Build
&lt;/h3&gt;

&lt;p&gt;If you still have the original unstripped build (or can reconstruct it):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Extract the crash address&lt;/strong&gt; from the core:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   gdb &lt;span class="nt"&gt;-c&lt;/span&gt; core &lt;span class="nt"&gt;-batch&lt;/span&gt; &lt;span class="nt"&gt;-ex&lt;/span&gt; &lt;span class="s2"&gt;"info registers"&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;rip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Get the memory map&lt;/strong&gt; of the process:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   gdb &lt;span class="nt"&gt;-c&lt;/span&gt; core &lt;span class="nt"&gt;-batch&lt;/span&gt; &lt;span class="nt"&gt;-ex&lt;/span&gt; &lt;span class="s2"&gt;"info proc mappings"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Compute the offset&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   offset = crash_address - base_address_of_binary
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Map the offset to source&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   addr2line &lt;span class="nt"&gt;-e&lt;/span&gt; /path/to/unstripped/myapp &lt;span class="nt"&gt;-f&lt;/span&gt; 0xOFFSET
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you the function and line number corresponding to the crash address.&lt;/p&gt;




&lt;h3&gt;
  
  
  A9 — No Symbols, No Reproduction: Fallback Forensics
&lt;/h3&gt;

&lt;p&gt;Even with no symbols and no way to reproduce, you can still extract useful information.&lt;/p&gt;

&lt;h4&gt;
  
  
  Inspect Registers
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gdb &lt;span class="nt"&gt;-c&lt;/span&gt; core &lt;span class="nt"&gt;-batch&lt;/span&gt; &lt;span class="nt"&gt;-ex&lt;/span&gt; &lt;span class="s2"&gt;"info registers"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Null pointers (&lt;code&gt;rax&lt;/code&gt;, &lt;code&gt;rdi&lt;/code&gt;, etc. equal to &lt;code&gt;0x0&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;Suspicious addresses in your binary’s range
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Inspect Instructions Around the Crash
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gdb &lt;span class="nt"&gt;-c&lt;/span&gt; core &lt;span class="nt"&gt;-batch&lt;/span&gt; &lt;span class="nt"&gt;-ex&lt;/span&gt; &lt;span class="s2"&gt;"x/20i &lt;/span&gt;&lt;span class="nv"&gt;$rip&lt;/span&gt;&lt;span class="s2"&gt;-40"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might see something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mov    %rax,%rdi
test   %rdi,%rdi
je     &amp;lt;skip&amp;gt;
mov    (%rdi),%rdx   ← crash here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;rdi&lt;/code&gt; is &lt;code&gt;0x0&lt;/code&gt;, you can infer a &lt;strong&gt;null pointer dereference&lt;/strong&gt;, even without symbols.&lt;/p&gt;




&lt;h2&gt;
  
  
  Path B — No Core File Generated
&lt;/h2&gt;

&lt;h3&gt;
  
  
  B1 — Check Core Dump Settings
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ulimit&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; /proc/sys/kernel/core_pattern
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;ulimit -c&lt;/code&gt; is &lt;code&gt;0&lt;/code&gt;, core dumps are disabled for your shell or service.&lt;/p&gt;




&lt;h3&gt;
  
  
  B2 — Enable Core Dumps
&lt;/h3&gt;

&lt;p&gt;Temporary (current shell):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ulimit&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; unlimited
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Permanent (system‑wide):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"* soft core unlimited"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; /etc/security/limits.conf
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"* hard core unlimited"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; /etc/security/limits.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may need to log out and back in, or restart services.&lt;/p&gt;




&lt;h3&gt;
  
  
  B3 — Set Core File Location
&lt;/h3&gt;

&lt;p&gt;Configure a directory for core files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"/var/core/core.%e.%p.%t"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /proc/sys/kernel/core_pattern
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pattern includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;%e&lt;/code&gt; — executable name
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;%p&lt;/code&gt; — PID
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;%t&lt;/code&gt; — timestamp
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  B4 — Fix Permissions
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/core
&lt;span class="nb"&gt;sudo chmod &lt;/span&gt;1777 /var/core
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures any process can write core files there.&lt;/p&gt;




&lt;h3&gt;
  
  
  B5 — Test Core Dump Generation
&lt;/h3&gt;

&lt;p&gt;Create a small crash program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compile and run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;g++ &lt;span class="nt"&gt;-g&lt;/span&gt; crash_test.cpp &lt;span class="nt"&gt;-o&lt;/span&gt; crash_test
./crash_test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify that a core file appears in &lt;code&gt;/var/core&lt;/code&gt; (or your configured directory).&lt;/p&gt;




&lt;h3&gt;
  
  
  B6 — Rerun the Crashed Application
&lt;/h3&gt;

&lt;p&gt;Now rerun the real application under the same conditions.&lt;br&gt;&lt;br&gt;
When it crashes, it should generate a core file.&lt;/p&gt;

&lt;p&gt;Then return to &lt;strong&gt;Path A&lt;/strong&gt; and continue from &lt;strong&gt;A2&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common Pitfalls
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Core dumps disabled in production (&lt;code&gt;ulimit -c 0&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;Stripped binaries deployed without archiving symbol files
&lt;/li&gt;
&lt;li&gt;Mismatched Build IDs between binary and symbol file
&lt;/li&gt;
&lt;li&gt;ASLR causing incorrect address mapping when computing offsets
&lt;/li&gt;
&lt;li&gt;Missing frame pointers (&lt;code&gt;-fomit-frame-pointer&lt;/code&gt;) breaking backtraces
&lt;/li&gt;
&lt;li&gt;Systemd or other service managers overriding &lt;code&gt;ulimit&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Symbol files not stored or indexed by Build ID
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Quick Reference Table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Enable cores&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ulimit -c unlimited&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Find cores&lt;/td&gt;
&lt;td&gt;&lt;code&gt;find / -name "core*"&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Check symbols&lt;/td&gt;
&lt;td&gt;&lt;code&gt;file ./myapp&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Get Build ID&lt;/td&gt;
&lt;td&gt;&lt;code&gt;readelf -n ./myapp&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Debug with symbols&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gdb -s myapp.dbg -e myapp -c core&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Map address&lt;/td&gt;
&lt;td&gt;&lt;code&gt;addr2line -e myapp -f 0xOFFSET&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Check core pattern&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cat /proc/sys/kernel/core_pattern&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Pro Tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Always compile with &lt;code&gt;-g&lt;/code&gt;, then strip separately for release.
&lt;/li&gt;
&lt;li&gt;Store symbol files indexed by Build ID in a central, backed‑up location.
&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;-fno-omit-frame-pointer&lt;/code&gt; for more reliable backtraces.
&lt;/li&gt;
&lt;li&gt;Test core dump generation in a staging environment that mirrors production.
&lt;/li&gt;
&lt;li&gt;Automate core collection and symbol archiving as part of your deployment pipeline.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This workflow covers every crash scenario — from “no core file” to “no symbols” to “full debug context.”&lt;br&gt;&lt;br&gt;
Bookmark it, share it with your team, and use it as your standard operating procedure for production crash analysis.&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>cordump</category>
      <category>legacy</category>
      <category>linux</category>
    </item>
    <item>
      <title>Beyond New and Delete: Engineering Approach with gsl::owner, std::span and clang-tidy</title>
      <dc:creator>Rui-Tech</dc:creator>
      <pubDate>Sun, 26 Apr 2026 15:27:41 +0000</pubDate>
      <link>https://dev.to/legacycpp/beyond-new-and-delete-engineering-approach-with-gslowner-stdspan-and-clang-tidy-27ob</link>
      <guid>https://dev.to/legacycpp/beyond-new-and-delete-engineering-approach-with-gslowner-stdspan-and-clang-tidy-27ob</guid>
      <description>&lt;p&gt;In my previous articles, &lt;a href="https://dev.to/legacycpp/beyond-new-and-delete-a-practical-guide-to-refactoring-raw-pointers-to-smart-pointers-3pcd"&gt;Beyond new and delete: A Practical Guide to Refactoring Raw Pointers to Smart Pointers&lt;/a&gt; and &lt;a href="https://dev.to/legacycpp/beyond-new-and-delete-to-weak-pointer-10l6"&gt;Beyond new and delete: to Weak Pointer&lt;/a&gt;, I explained how to refactor raw pointers into &lt;code&gt;unique_ptr&lt;/code&gt;, &lt;code&gt;shared_ptr&lt;/code&gt;, &lt;code&gt;weak_ptr&lt;/code&gt;, and references.&lt;/p&gt;

&lt;p&gt;But swapping pointer types is only half the battle. A successful refactoring also requires a &lt;strong&gt;systematic engineering process&lt;/strong&gt; — one that combines ownership analysis, modern C++ types, static analysis, and incremental testing to ensure safety and correctness.&lt;/p&gt;

&lt;p&gt;In this article, we focus on that engineering workflow:&lt;br&gt;
&lt;strong&gt;Audit &amp;amp; Annotate&lt;/strong&gt; → &lt;strong&gt;Static Analysis&lt;/strong&gt; → &lt;strong&gt;Replace&lt;/strong&gt; → &lt;strong&gt;Refactor Incrementally&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Audit &amp;amp; Annotate&lt;/strong&gt; – Mark owning vs observer pointers, use GSL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Static Analysis&lt;/strong&gt; – Enable &lt;code&gt;-Wall&lt;/code&gt;, run clang-tidy, add sanitizers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Replace with Modern Types&lt;/strong&gt; – &lt;code&gt;unique_ptr&lt;/code&gt;, &lt;code&gt;shared_ptr&lt;/code&gt;, &lt;code&gt;span&lt;/code&gt;, references&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Refactor Incrementally&lt;/strong&gt; – Start with leaf modules, remove manual &lt;code&gt;delete&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Step 1. Audit and Annotate Ownership
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; Make ownership explicit before changing any code.&lt;/p&gt;

&lt;p&gt;Use comments or annotations to mark which pointers own memory and which do not.&lt;br&gt;&lt;br&gt;
Consider using the &lt;strong&gt;Guidelines Support Library (GSL)&lt;/strong&gt; – available via vcpkg, Conan, or as a header‑only library (&lt;code&gt;#include &amp;lt;gsl/gsl&amp;gt;&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;gsl::owner&amp;lt;T*&amp;gt;&lt;/code&gt; for owning pointers.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;T*&lt;/code&gt; or &lt;code&gt;gsl::not_null&amp;lt;T*&amp;gt;&lt;/code&gt; for non-owning pointers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;gsl/gsl&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gsl&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;not_null&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyClass&lt;/span&gt;&lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ptr is guaranteed non-null - no need to check!&lt;/span&gt;
    &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;legacy_owner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gsl&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyClass&lt;/span&gt;&lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;owned&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// This raw pointer OWNS the memory&lt;/span&gt;
    &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;owned&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2. Use Static Analysis and Compiler Options
&lt;/h2&gt;

&lt;p&gt;Enable compiler warnings for unsafe pointer usage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;GCC/Clang: &lt;code&gt;-Wall -Wextra -Werror&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;MSVC: &lt;code&gt;/W4&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;or Use static analysis tools to catch raw pointer misuse:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;clang-tidy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cppcheck&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Run clang-tidy with Core Guidelines checks&lt;/span&gt;
clang-tidy &lt;span class="nt"&gt;--checks&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'cppcoreguidelines-owning-memory,modernize-*'&lt;/span&gt; file.cpp 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other useful tools: LeakSanitizer, Valgrind, Dr. Memory.&lt;/p&gt;

&lt;p&gt;Typical warnings are listed below.&lt;/p&gt;

&lt;h3&gt;
  
  
  Warning 1: Missing 'gsl::owner' on allocated pointer
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;  &lt;span class="c1"&gt;// warning here&lt;/span&gt;
&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;warning: initializing non-owner 'int *' with a newly created 'gsl::owner&amp;lt;&amp;gt;' [cppcoreguidelines-owning-memory]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fix&lt;/strong&gt;: &lt;code&gt;gsl::owner&amp;lt;int*&amp;gt; data = new int[100];&lt;/code&gt; or use &lt;code&gt;std::unique_ptr&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Warning 2: Deleting a non-owner pointer
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// missing owner annotation&lt;/span&gt;
&lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;              &lt;span class="c1"&gt;// warning here&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;warning: deleting a pointer through a type that is not marked 'gsl::owner&amp;lt;&amp;gt;' [cppcoreguidelines-owning-memory]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fix&lt;/strong&gt;: Mark with &lt;code&gt;gsl::owner&lt;/code&gt; or use smart pointer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Warning 3: Returning raw pointer from factory (ownership unclear)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;make_int&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;        &lt;span class="c1"&gt;// warning: returning raw pointer&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;warning: function returns a raw pointer that may be an owner [cppcoreguidelines-owning-memory]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fix&lt;/strong&gt;: &lt;code&gt;std::unique_ptr&amp;lt;int&amp;gt; make_int()&lt;/code&gt; or mark as &lt;code&gt;gsl::owner&amp;lt;int*&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Warning 4: Assignment loses ownership
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;gsl&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;   &lt;span class="c1"&gt;// warning: owner assigned to non-owner&lt;/span&gt;
    &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;warning: initializing non-owner 'int *' with a newly created 'gsl::owner&amp;lt;&amp;gt;' [cppcoreguidelines-owning-memory]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fix&lt;/strong&gt;: &lt;code&gt;gsl::owner&amp;lt;int*&amp;gt; p = create()&lt;/code&gt;; or use &lt;code&gt;auto p = create();&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Warning 5: Using std::unique_ptr with raw delete
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;make_unique&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;          &lt;span class="c1"&gt;// warning: manual delete on smart pointer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;warning: 'delete' applied to pointer that is owned by a smart pointer [cppcoreguidelines-owning-memory]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fix&lt;/strong&gt;: Remove manual &lt;code&gt;delete&lt;/code&gt; – the smart pointer handles it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3. Replace with Modern Types
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Ownership/Usage&lt;/th&gt;
&lt;th&gt;Modern C++ Type&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sole ownership&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::unique_ptr&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;std::make_unique&amp;lt;T&amp;gt;()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shared ownership&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::shared_ptr&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;std::make_shared&amp;lt;T&amp;gt;()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-owning, never null&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;T&amp;amp;&lt;/code&gt; or &lt;code&gt;gsl::not_null&amp;lt;T*&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Prefer references when possible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-owning, may be null&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;T*&lt;/code&gt; (with optional GSL annotation)&lt;/td&gt;
&lt;td&gt;Raw pointer is fine as an observer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Array/view, non-owning&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::span&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;C++20 (or GSL span for older standards)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Non-owning view over array/vector&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 For dynamic arrays, consider &lt;code&gt;std::vector&amp;lt;T&amp;gt;&lt;/code&gt; over &lt;code&gt;std::unique_ptr&amp;lt;T[]&amp;gt;&lt;/code&gt; unless you need a specific allocator or C API compatibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4. Refactor Incrementally
&lt;/h2&gt;

&lt;p&gt;Start with leaf modules (fewest dependencies).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replace &lt;code&gt;gsl::owner&amp;lt;T*&amp;gt;&lt;/code&gt; with &lt;code&gt;std::unique_ptr&amp;lt;T&amp;gt;&lt;/code&gt; or &lt;code&gt;std::shared_ptr&amp;lt;T&amp;gt;&lt;/code&gt; as appropriate.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;std::span&amp;lt;T&amp;gt;&lt;/code&gt; for functions that take raw array pointers and sizes.&lt;/li&gt;
&lt;li&gt;Update function signatures and member variables.&lt;/li&gt;
&lt;li&gt;Remove manual &lt;code&gt;delete&lt;/code&gt; calls.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  An Example: Step‑by‑Step Refactoring
&lt;/h2&gt;

&lt;p&gt;Before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;               &lt;span class="c1"&gt;// arr is not owned&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gsl&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyClass&lt;/span&gt;&lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;         &lt;span class="c1"&gt;// obj is owned&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;caller&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;MyClass&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;mc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;MyClass&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;mc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;memory&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                &lt;span class="c1"&gt;// Non-owning view&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;unique_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyClass&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;      &lt;span class="c1"&gt;// Ownership transferred&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;caller&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;make_unique&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="c1"&gt;// No delete needed&lt;/span&gt;

    &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;mc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;make_unique&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyClass&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mc&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="c1"&gt;// No delete needed&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  When NOT to Refactor
&lt;/h2&gt;

&lt;p&gt;Refactoring raw pointers isn't always the right move. Consider postponing or skipping when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Performance‑critical hot paths – the (small) overhead of smart pointers might matter (measure first).&lt;/li&gt;
&lt;li&gt;Codebases frozen for certification – aviation, medical, or safety‑critical systems.&lt;/li&gt;
&lt;li&gt;Interfacing with C libraries – raw pointers are often unavoidable there.&lt;/li&gt;
&lt;li&gt;The code is about to be deprecated – don't invest time in dead code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Reference: clang-tidy Commands for Raw Pointer Refactoring
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Check Commands (Analyze Only)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;clang-tidy --checks='cppcoreguidelines-owning-memory' file.cpp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Detect missing &lt;code&gt;gsl::owner&lt;/code&gt; annotations and improper deletions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;clang-tidy --checks='modernize-make-unique' file.cpp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Find raw &lt;code&gt;new&lt;/code&gt; that can be replaced with &lt;code&gt;std::make_unique&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;clang-tidy --checks='modernize-make-shared' file.cpp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Find raw &lt;code&gt;new&lt;/code&gt; that can be replaced with &lt;code&gt;std::make_shared&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;clang-tidy --checks='modernize-use-auto' file.cpp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Find verbose type names that can be replaced with &lt;code&gt;auto&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;clang-tidy --checks='modernize-use-nullptr' file.cpp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Find &lt;code&gt;NULL&lt;/code&gt; or &lt;code&gt;0&lt;/code&gt; that can be replaced with &lt;code&gt;nullptr&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;clang-tidy --checks='cppcoreguidelines-owning-memory,modernize-*' file.cpp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Run all relevant checks together&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Fix Commands (Apply Changes)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;clang-tidy --fix --checks='modernize-make-unique' file.cpp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Automatically replace &lt;code&gt;new&lt;/code&gt; with &lt;code&gt;std::make_unique&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;clang-tidy --fix --checks='modernize-make-shared' file.cpp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Automatically replace &lt;code&gt;new&lt;/code&gt; with &lt;code&gt;std::make_shared&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;clang-tidy --fix --checks='modernize-use-auto' file.cpp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Automatically replace verbose types with &lt;code&gt;auto&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;clang-tidy --fix --checks='modernize-use-nullptr' file.cpp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Automatically replace &lt;code&gt;NULL&lt;/code&gt; with &lt;code&gt;nullptr&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;clang-tidy --fix --checks='cppcoreguidelines-owning-memory' file.cpp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Add &lt;code&gt;gsl::owner&lt;/code&gt; annotations (manual review still recommended)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Recommended Workflow with clang-tidy
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Step 1: Run checks to see what needs fixing&lt;/span&gt;
clang-tidy &lt;span class="nt"&gt;--checks&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'cppcoreguidelines-owning-memory,modernize-*'&lt;/span&gt; file.cpp

&lt;span class="c"&gt;# Step 2: Apply automatic fixes safely&lt;/span&gt;
clang-tidy &lt;span class="nt"&gt;--fix&lt;/span&gt; &lt;span class="nt"&gt;--checks&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'modernize-make-unique,modernize-make-shared,modernize-use-auto,modernize-use-nullptr'&lt;/span&gt; file.cpp

&lt;span class="c"&gt;# Step 3: Re-run checks to verify fixes&lt;/span&gt;
clang-tidy &lt;span class="nt"&gt;--checks&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'cppcoreguidelines-owning-memory'&lt;/span&gt; file.cpp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;A professional refactoring from raw pointers to modern C++ involves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Explicitly annotating ownership (with GSL or comments)&lt;/li&gt;
&lt;li&gt;Using compiler warnings and static analysis&lt;/li&gt;
&lt;li&gt;Replacing with the right smart pointer or view type (&lt;code&gt;unique_ptr&lt;/code&gt;, &lt;code&gt;shared_ptr&lt;/code&gt;, &lt;code&gt;std::span&lt;/code&gt;, references)&lt;/li&gt;
&lt;li&gt;Testing and reviewing at every step&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach produces safer, more maintainable, and truly modern C++ code – without the sleepless nights hunting for memory leaks.&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>legacy</category>
      <category>refactor</category>
      <category>clangtidy</category>
    </item>
    <item>
      <title>Beyond new and delete: to Weak Pointer</title>
      <dc:creator>Rui-Tech</dc:creator>
      <pubDate>Mon, 20 Apr 2026 09:15:11 +0000</pubDate>
      <link>https://dev.to/legacycpp/beyond-new-and-delete-to-weak-pointer-10l6</link>
      <guid>https://dev.to/legacycpp/beyond-new-and-delete-to-weak-pointer-10l6</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/legacycpp/beyond-new-and-delete-a-practical-guide-to-refactoring-raw-pointers-to-smart-pointers-3pcd"&gt;previous article&lt;/a&gt;, we left one case untouched: the transition from raw pointers to weak_ptr. That's exactly what we'll dive into today.&lt;/p&gt;

&lt;p&gt;Use shared_ptr when multiple parts of your system need to keep an object alive, and you can't predict which part will outlive the others. But shared_ptr has a fatal flaw: cyclic references.&lt;/p&gt;

&lt;p&gt;When two shared_ptrs point to each other, neither can die. They hold each other hostage forever. The result? A memory leak that never gets cleaned up.&lt;/p&gt;

&lt;p&gt;Let me break it down step by step.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Problem: What happens when objects point to each other?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Normal case (no cycle)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shared_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mother&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Owning reference&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;alice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;make_shared&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;bob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;make_shared&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// alice's reference count = 1&lt;/span&gt;
&lt;span class="c1"&gt;// bob's reference count = 1&lt;/span&gt;
&lt;span class="c1"&gt;// When they go out of scope, both are destroyed ✅&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The cyclic problem
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shared_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mother&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shared_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;father&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;alice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;make_shared&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// alice ref count = 1&lt;/span&gt;
&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;bob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;make_shared&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;    &lt;span class="c1"&gt;// bob ref count = 1&lt;/span&gt;

&lt;span class="n"&gt;alice&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;father&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bob&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// bob's ref count becomes 2&lt;/span&gt;
&lt;span class="n"&gt;bob&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;mother&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;alice&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// alice's ref count becomes 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Now what happens when &lt;code&gt;alice&lt;/code&gt; and &lt;code&gt;bob&lt;/code&gt; go out of scope?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;alice&lt;/code&gt; (the variable) is destroyed → alice's ref count drops from 2 → 1&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bob&lt;/code&gt; (the variable) is destroyed → bob's ref count drops from 2 → 1&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Both objects still have ref count = 1!&lt;/strong&gt; They point to each other, so neither can be destroyed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MEMORY LEAK&lt;/strong&gt; 💥&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Solution: &lt;code&gt;weak_ptr&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;weak_ptr&lt;/code&gt; is like a "peek" at the object — it doesn't increase the reference count.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shared_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mother&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Owning (increases count)&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;weak_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;father&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    &lt;span class="c1"&gt;// Observing (doesn't increase count)&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;alice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;make_shared&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// alice count = 1&lt;/span&gt;
&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;bob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;make_shared&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;    &lt;span class="c1"&gt;// bob count = 1&lt;/span&gt;

&lt;span class="n"&gt;alice&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;father&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bob&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// bob's count stays 1 (weak_ptr doesn't affect it)&lt;/span&gt;
&lt;span class="n"&gt;bob&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;mother&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;alice&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// alice's count becomes 2&lt;/span&gt;

&lt;span class="c1"&gt;// When variables go out of scope:&lt;/span&gt;
&lt;span class="c1"&gt;// bob count: 1 → 0 (destroyed)&lt;/span&gt;
&lt;span class="c1"&gt;// alice count: 2 → 1 → 0 (destroyed when bob's weak_ptr expires)&lt;/span&gt;
&lt;span class="c1"&gt;// NO LEAK! ✅&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using &lt;code&gt;weak_ptr&lt;/code&gt;: The &lt;code&gt;.lock()&lt;/code&gt; method
&lt;/h2&gt;

&lt;p&gt;You can't use a &lt;code&gt;weak_ptr&lt;/code&gt; directly — you must first "lock" it to get a temporary &lt;code&gt;shared_ptr&lt;/code&gt;. .lock() atomically checks existence and acquires a shared_ptr in one thread-safe operation — there is no other safe way to access a weak_ptr's target.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// BAD: Can't use weak_ptr directly&lt;/span&gt;
&lt;span class="n"&gt;father&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// Compiler error!&lt;/span&gt;

&lt;span class="c1"&gt;// GOOD: Lock it first&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;father&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  &lt;span class="c1"&gt;// Try to get shared_ptr&lt;/span&gt;
    &lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;           &lt;span class="c1"&gt;// Use it safely&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// The object has been destroyed&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Father is gone&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Real-World Examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Parent-child relationships
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Node&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shared_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Owning&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;weak_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                   &lt;span class="c1"&gt;// Observing (back-pointer)&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Event observers
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;weak_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ClickObserver&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;observers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Non-owning&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;weakObs&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;observers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;obs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;weakObs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;obs&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// Clean up dead observers&lt;/span&gt;
        &lt;span class="n"&gt;observers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;erase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;remove_if&lt;/span&gt;&lt;span class="p"&gt;(...));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Caches
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ImageCache&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;weak_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shared_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Still in use, return it&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// Not in cache or expired, load new image&lt;/span&gt;
        &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;make_shared&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Store as weak_ptr&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The &lt;code&gt;shared_ptr.get()&lt;/code&gt; -&amp;gt; weak_ptr
&lt;/h2&gt;

&lt;p&gt;The comment about &lt;code&gt;.get()&lt;/code&gt; means: If you ever write this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// BAD pattern&lt;/span&gt;
&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shared_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Widget&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;make_shared&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Widget&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;Widget&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// Storing raw pointer&lt;/span&gt;
&lt;span class="c1"&gt;// Later: use raw somewhere else — DANGEROUS!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's usually a sign you should use &lt;code&gt;weak_ptr&lt;/code&gt; instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// GOOD pattern&lt;/span&gt;
&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shared_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Widget&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;make_shared&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Widget&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;weak_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Widget&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;wp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Non-owning reference&lt;/span&gt;
&lt;span class="c1"&gt;// Later: wp.lock() to safely access&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;shared_ptr&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;weak_ptr&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Owns the object&lt;/td&gt;
&lt;td&gt;Observes the object&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Increases ref count&lt;/td&gt;
&lt;td&gt;Doesn't affect ref count&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keeps object alive&lt;/td&gt;
&lt;td&gt;Object can die&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Always valid (until destroyed)&lt;/td&gt;
&lt;td&gt;May be expired&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Direct access with &lt;code&gt;-&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Must call &lt;code&gt;.lock()&lt;/code&gt; first&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;When to use &lt;code&gt;weak_ptr&lt;/code&gt;:&lt;/strong&gt; Any time you need a reference to an object but don't want to be responsible for keeping it alive — especially parent back-pointers, observers, and caches.&lt;/p&gt;

&lt;p&gt;Does this make the cyclic reference problem clearer?&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>legacy</category>
      <category>refactoring</category>
      <category>ptr</category>
    </item>
    <item>
      <title>Beyond new and delete: A Practical Guide to Refactoring Raw Pointers to Smart Pointers</title>
      <dc:creator>Rui-Tech</dc:creator>
      <pubDate>Fri, 17 Apr 2026 05:45:18 +0000</pubDate>
      <link>https://dev.to/legacycpp/beyond-new-and-delete-a-practical-guide-to-refactoring-raw-pointers-to-smart-pointers-3pcd</link>
      <guid>https://dev.to/legacycpp/beyond-new-and-delete-a-practical-guide-to-refactoring-raw-pointers-to-smart-pointers-3pcd</guid>
      <description>&lt;p&gt;You've been there. You inherit a codebase filled with &lt;code&gt;Widget* w = new Widget()&lt;/code&gt;, manual &lt;code&gt;delete&lt;/code&gt; calls scattered across error-prone destructors, and the occasional use-after-free that crashes in production once a week.&lt;/p&gt;

&lt;p&gt;You know C++11's smart pointers are the answer. But refactoring a raw pointer to &lt;code&gt;std::unique_ptr&lt;/code&gt;, &lt;code&gt;std::shared_ptr&lt;/code&gt;, or even back to a plain reference isn't always obvious. The core question is: &lt;strong&gt;Who owns this object?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this article, we'll build a decision framework. In 15 minutes, you'll learn how to mechanically refactor raw pointers and when to choose each smart pointer—or avoid them altogether.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Decision Workflow (15-Second Check)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Raw Pointer?
    │
    ├─ Does it OWN the object?
    │       │
    │       ├─ NO  → raw reference (&amp;amp;) or raw pointer (*)
    │       │        (never delete)
    │       │
    │       └─ YES → Is ownership EXCLUSIVE?
    │                   │
    │                   ├─ YES → std::unique_ptr ← 80% of cases
    │                   │
    │                   └─ NO  → Is ownership SHARED?
    │                               │
    │                               ├─ YES → Is there a CYCLE?
    │                               │           │
    │                               │           ├─ YES → std::weak_ptr
    │                               │           │
    │                               │           └─ NO  → std::shared_ptr
    │                               │
    │                               └─ NO  → Re-examine design
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The 3-Question Drill:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Answer → Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Owns?&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No → Raw reference/pointer (never delete)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Exclusive?&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes → &lt;code&gt;unique_ptr&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Shared?&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes → &lt;code&gt;shared_ptr&lt;/code&gt; (check for cycles → &lt;code&gt;weak_ptr&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;That's it.&lt;/strong&gt; 80% of raw pointers become &lt;code&gt;unique_ptr&lt;/code&gt;. 15% become raw references. 5% become &lt;code&gt;shared_ptr&lt;/code&gt;/&lt;code&gt;weak_ptr&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Golden Rule of Refactoring
&lt;/h2&gt;

&lt;p&gt;Never change behavior while refactoring. Start with a single raw pointer. Ask three questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Is this pointer nullable? (Can it be &lt;code&gt;nullptr&lt;/code&gt;?)&lt;/li&gt;
&lt;li&gt;Who is responsible for deleting the object?&lt;/li&gt;
&lt;li&gt;Is ownership shared or unique?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once you answer those, the path becomes clear.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Obvious Case — Exclusive Ownership → &lt;code&gt;std::unique_ptr&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;unique_ptr&lt;/code&gt; when exactly one part of the code owns the object, but the pointer might be moved or transferred.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Signs you need &lt;code&gt;unique_ptr&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The raw pointer is deleted in the same class that creates it.&lt;/li&gt;
&lt;li&gt;The pointer is never copied (only moved or passed as a raw pointer to functions that don't store it).&lt;/li&gt;
&lt;li&gt;You see &lt;code&gt;delete ptr;&lt;/code&gt; in a destructor and nowhere else.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Before refactoring:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Connection&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;socket_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Socket&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;socket_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Manual move/copy? Omitted for brevity — disaster waiting.&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;Socket&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;socket_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After refactoring:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Connection&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;socket_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;make_unique&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Socket&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="c1"&gt;// Destructor auto-deletes. Move is automatic.&lt;/span&gt;
    &lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;unique_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Socket&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;socket_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key nuance:&lt;/strong&gt; You can still pass a raw pointer to a function that doesn't own the object (e.g., &lt;code&gt;void send(Socket* s)&lt;/code&gt;). Use &lt;code&gt;.get()&lt;/code&gt; for that. But never &lt;code&gt;.release()&lt;/code&gt; unless you truly mean to transfer ownership.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Heuristic:&lt;/strong&gt; If you would have used &lt;code&gt;std::auto_ptr&lt;/code&gt; (RIP), use &lt;code&gt;unique_ptr&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Shared Ownership → &lt;code&gt;std::shared_ptr&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;shared_ptr&lt;/code&gt; when multiple parts of the system need to keep the object alive and you cannot predict which one will outlive the others.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Signs you need &lt;code&gt;shared_ptr&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The pointer is stored in several containers or callbacks.&lt;/li&gt;
&lt;li&gt;You have &lt;code&gt;std::vector&lt;/code&gt; and multiple threads or components delete items unpredictably.&lt;/li&gt;
&lt;li&gt;You find yourself implementing reference counting manually (e.g., &lt;code&gt;AddRef&lt;/code&gt;/&lt;code&gt;Release&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Before refactoring:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Node&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This leaks if a child is referenced from two parents. Don't do this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After refactoring:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Node&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;enable_shared_from_this&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shared_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shared_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// No manual destructor.&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The cost:&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;shared_ptr&lt;/code&gt; doubles the size (two pointers: object + control block) and uses atomic increments (slower, but fine for most apps). Only reach for &lt;code&gt;shared_ptr&lt;/code&gt; when &lt;code&gt;unique_ptr&lt;/code&gt; is impossible.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Observer Case — Breaking Cycles → &lt;code&gt;std::weak_ptr&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;shared_ptr&lt;/code&gt; has a fatal flaw: &lt;strong&gt;cyclic references&lt;/strong&gt;. If two &lt;code&gt;shared_ptr&lt;/code&gt;s point to each other, they never die.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shared_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mother&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shared_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;father&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Cycle!&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shared_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mother&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Owning&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;weak_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;father&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    &lt;span class="c1"&gt;// Observing (no cycle)&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use &lt;code&gt;weak_ptr&lt;/code&gt; when you need a non-owning reference to an object managed by &lt;code&gt;shared_ptr&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Full explanation and refactoring techniques for &lt;code&gt;weak_ptr&lt;/code&gt; → &lt;a href="https://dev.to/legacycpp/beyond-new-and-delete-to-weak-pointer-10l6"&gt;see  the next article&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The No-Ownership Case — Raw References &amp;amp; Raw Pointers
&lt;/h2&gt;

&lt;p&gt;Smart pointers express ownership. Not every pointer needs to be smart. In fact, using a &lt;code&gt;shared_ptr&lt;/code&gt; for every single pointer is an anti-pattern (slow, bloated, semantically wrong).&lt;/p&gt;

&lt;p&gt;Use plain references (&lt;code&gt;&amp;amp;&lt;/code&gt;) or raw pointers (&lt;code&gt;*&lt;/code&gt;) for non-owning observers when you are certain the lifetime is longer than the use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use a raw reference:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The object must exist (no &lt;code&gt;nullptr&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;You are not storing it for later (e.g., function parameter).&lt;/li&gt;
&lt;li&gt;Example: &lt;code&gt;void draw(const Shape&amp;amp; shape);&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When to use a raw pointer:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The observer can be null.&lt;/li&gt;
&lt;li&gt;You need to reseat it (references can't be reassigned).&lt;/li&gt;
&lt;li&gt;Example: &lt;code&gt;void setLogger(Logger* logger) { logger_ = logger; }&lt;/code&gt; – but only if the &lt;code&gt;Logger&lt;/code&gt; outlives this object.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The critical rule:&lt;/strong&gt;&lt;br&gt;
A raw pointer or reference must never be deleted. If you see &lt;code&gt;delete ptr&lt;/code&gt; on a raw pointer, you made a wrong turn.&lt;/p&gt;


&lt;h2&gt;
  
  
  Real Refactoring Example — A Cache System
&lt;/h2&gt;

&lt;p&gt;Let's refactor a small in-memory cache from raw pointers to smart pointers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before (broken):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Cache&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;unordered_map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;Cache&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="c1"&gt;// Usage: who deletes the Data? Cache does, but what if two caches share it?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After (clear ownership):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Cache&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Cache owns the Data exclusively.&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;unordered_map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;unique_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;unique_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Returns non-owning observer&lt;/span&gt;
    &lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now ownership is explicit. The cache destroys the data. Callers can observe but not delete.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common Pitfalls During Refactoring
&lt;/h2&gt;

&lt;p&gt;❌ &lt;strong&gt;Mixing ownership styles&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;std::shared_ptr&amp;lt;Widget&amp;gt; sp = std::make_unique&amp;lt;Widget&amp;gt;();&lt;/code&gt; // Works but confusing. Prefer consistent smart pointer types.&lt;/p&gt;

&lt;p&gt;❌ &lt;strong&gt;Using &lt;code&gt;shared_ptr&lt;/code&gt; for everything "just to be safe"&lt;/strong&gt;&lt;br&gt;
This hides design issues and kills performance (atomic ops). Refactor to &lt;code&gt;unique_ptr&lt;/code&gt; first.&lt;/p&gt;

&lt;p&gt;❌ &lt;strong&gt;Calling &lt;code&gt;.get()&lt;/code&gt; and storing the raw pointer long-term&lt;/strong&gt;&lt;br&gt;
That's just raw pointer ownership again. Store the smart pointer or use &lt;code&gt;weak_ptr&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;❌ &lt;strong&gt;Forgetting &lt;code&gt;make_unique&lt;/code&gt; / &lt;code&gt;make_shared&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Old: std::unique_ptr&amp;lt;Widget&amp;gt; p(new Widget());&lt;/span&gt;
&lt;span class="c1"&gt;// New:&lt;/span&gt;
&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;make_unique&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Widget&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;make_unique&lt;/code&gt; is exception-safe and slightly more efficient.&lt;/p&gt;




&lt;h2&gt;
  
  
  When Not to Refactor
&lt;/h2&gt;

&lt;p&gt;Some raw pointers are fine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Non-owning iterators into a buffer.&lt;/li&gt;
&lt;li&gt;Polymorphic casts in performance-critical loops (you still need to ensure lifetime).&lt;/li&gt;
&lt;li&gt;Legacy APIs that expect raw pointers and manage their own memory. Don't force &lt;code&gt;shared_ptr&lt;/code&gt; into a C-style callback.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In those cases, &lt;strong&gt;document the lifetime contract&lt;/strong&gt;: "This pointer is valid only during the call."&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion: Ownership Is Documentation
&lt;/h2&gt;

&lt;p&gt;Refactoring raw pointers to smart pointers isn't just about memory safety—it's about expressing intent. When I see &lt;code&gt;unique_ptr&lt;/code&gt;, I know: This object has a single, clear owner. When I see &lt;code&gt;shared_ptr&lt;/code&gt;, I know: Multiple agents collaborate here. When I see a raw reference, I know: I'm just visiting; don't delete.&lt;/p&gt;

&lt;p&gt;Next time you look at a &lt;code&gt;MyClass*&lt;/code&gt; member variable, ask: &lt;strong&gt;"Who owns this?"&lt;/strong&gt; Then pick the tool that answers that question in code.&lt;/p&gt;

&lt;p&gt;Your future self—and your teammates—will thank you.&lt;/p&gt;




</description>
      <category>cpp</category>
      <category>leagcy</category>
      <category>refactoring</category>
      <category>ptr</category>
    </item>
  </channel>
</rss>
