C++ Module 6 – References, pointers and memory
Dynamic memory in C++: new, delete and leaks
Create and destroy objects with new and delete, find leaks, double deletes and new[]/delete mismatches with sanitizers, then replace them with standard types.
What you will learn
- Create and destroy objects and arrays with new, delete, new[] and delete[]
- Recognise use after delete, double deletes, new[]/delete mismatches and leaks in sanitizer reports
- Find leaks on macOS, Linux and Windows with the tool each platform provides
- Replace manual memory management with std::vector and std::unique_ptr
Before you start
What you’ll learn · Before you start
What you will learn
- Create and destroy objects and arrays with new, delete, new[] and delete[]
- Recognise use after delete, double deletes, new[]/delete mismatches and leaks in sanitizer reports
- Find leaks on macOS, Linux and Windows with the tool each platform provides
- Replace manual memory management with std::vector and std::unique_ptr
Before you start
On this page
A new expression creates an object with dynamic storage duration: new int{42} reserves memory on the free
store (often called the heap), creates an int there and returns a pointer to it. The object is not tied to any
scope; it lives until a delete expression ends it, so delete p; destroys the object and gives its memory back.
Arrays have their own pair, new T[n] and delete[] p.
Every new needs exactly one matching delete, and that rule is easy to break. Forget the delete and the memory
stays reserved, a leak. Delete twice, or use the object after delete, and the program has undefined behaviour.
Release an array with plain delete and it is undefined again. This lesson shows each mistake as two compilers, the
sanitizers and macOS’s leaks tool report it, how to find leaks on each platform, and the replacement that modern code
uses instead: containers and smart pointers, which make delete disappear from ordinary code.
new and delete
#include <cstddef>
#include <print>
#include <string>
struct Student {
std::string name;
int marks;
Student(std::string n, int m) : name(std::move(n)), marks(m) { std::println(" Student {} created", name); }
~Student() { std::println(" Student {} destroyed", name); }
};
int main() {
int* count = new int{42}; // one int with dynamic storage duration
std::println("*count = {}", *count);
delete count; // ends its lifetime and gives the memory back
Student* s = new Student{"Asha", 72}; // new allocates, then runs the constructor
s->marks += 5;
std::println("{} has {} marks", s->name, s->marks);
delete s; // delete runs the destructor, then frees
std::size_t n = 4;
int* scores = new int[n](); // n ints, set to 0 by the ()
scores[n - 1] = 99;
std::println("scores {} {} {} {}", scores[0], scores[1], scores[2], scores[3]);
delete[] scores; // memory from new[] goes back with delete[]
} from session import run
run("""
clang++ -std=c++23 -Wall -Wextra -g -fsanitize=address new_delete.cpp -o new_delete && ./new_delete
g++-16 -std=c++23 -Wall -Wextra -g -fsanitize=address new_delete.cpp -o new_delete && ./new_delete
""") Output
$ clang++ -std=c++23 -Wall -Wextra -g -fsanitize=address new_delete.cpp -o new_delete && ./new_delete *count = 42 Student Asha created Asha has 77 marks Student Asha destroyed scores 0 0 0 99 $ g++-16 -std=c++23 -Wall -Wextra -g -fsanitize=address new_delete.cpp -o new_delete && ./new_delete *count = 42 Student Asha created Asha has 77 marks Student Asha destroyed scores 0 0 0 99
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 new_delete_session.py
new does two things, in order: it allocates memory, then it runs the constructor, which is why Student Asha created appears at the new line. delete reverses them: it runs the destructor, then frees the memory. new int[n]
creates n ints whose count may be known only at run time, and the empty parentheses in new int[n]() set each one
to zero; without them the ints would hold no defined value. The sanitizer builds of both compilers ran the program
without a report, because every object was deleted exactly once and in the right form.
Pointers on the stack, objects on the free store
Text description of the diagram
The diagram has two areas side by side.
On the left is the stack, with three local pointer variables of main: count, an int*; s, a Student*; and old, an int* after delete old.
On the right is the free store, with the objects that new created: an int holding 42, a Student holding Asha and 77, a dashed box of freed memory where no object is any more, and a dashed box for an int[100] array that no pointer refers to.
Arrows connect the pointers to their objects: count points to the int 42 and s to the Student. A dashed arrow labelled "dangling" goes from old to the freed memory: the pointer still holds the address, but the object is gone. No arrow reaches the int[100] array: nothing can delete it any more, so it is a leak.
The pointer variables, such as count and s, are ordinary local variables: they live on the stack and disappear at
the end of main. The objects they point to live on the free store until delete ends them. Nothing connects the two
lifetimes, and that gap is where every bug in this lesson comes from: old in the diagram still holds an address after
its object was deleted, and the int[100] block has lost its last pointer.
Mistake 1: using an object after delete
After delete, the pointer still holds the old address, but the object is gone and the standard makes every pointer
into that storage invalid ([basic.stc]). Reading through it is undefined behaviour:
#include <print>
#include <string>
int main() {
std::string* name = new std::string{"Ravi"};
delete name;
std::println("{}", name->size()); // the string has been destroyed: undefined behaviour
} from session import run
run("""
g++-16 -std=c++23 -Wall -Wextra -g -fsanitize=address use_after_free.cpp -o use_after_free && ./use_after_free
""") Output
$ g++-16 -std=c++23 -Wall -Wextra -g -fsanitize=address use_after_free.cpp -o use_after_free && ./use_after_free
==…==ERROR: AddressSanitizer: heap-use-after-free on address 0x…
READ of size 8 at 0x… thread T0
#1 in main use_after_free.cpp:7
0x… is located 8 bytes inside of 32-byte region [0x…,0x…)
freed by thread T0 here:
#1 in main use_after_free.cpp:6
previously allocated by thread T0 here:
#1 in main use_after_free.cpp:5
SUMMARY: AddressSanitizer: heap-use-after-free
[42 more lines of the report left out]
/bin/sh: line 1: … Abort trap: 6 ./use_after_free
[exit status 134]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 use_after_free_session.py
AddressSanitizer reports a heap-use-after-free and prints three stacks: the bad read on line 7, the delete that
freed the memory on line 6 and the new that allocated it on line 5. The read was 8 bytes into a 32-byte block,
which is where libstdc++’s std::string keeps its size. A pointer that may outlive its object is a design smell; the
quick fix is to set it to nullptr right after delete, and the real fix is to give the object an owner, as the last
section shows.
Mistake 2: deleting twice
Passing an invalid pointer to a deallocation function is undefined behaviour too, so deleting the same object twice is not merely wasteful:
#include <print>
int main() {
int* seats = new int{40};
std::println("seats {}", *seats);
delete seats;
delete seats; // the same object a second time: undefined behaviour
std::println("done");
} from session import run
run("""
clang++ -std=c++23 -Wall -Wextra double_delete.cpp -o double_delete && ./double_delete
clang++ -std=c++23 -g -fsanitize=address double_delete.cpp -o double_delete && ./double_delete
""") Output
$ clang++ -std=c++23 -Wall -Wextra double_delete.cpp -o double_delete && ./double_delete
seats 40
/bin/sh: line 1: … Trace/BPT trap: 5 ./double_delete
[exit status 133]
$ clang++ -std=c++23 -g -fsanitize=address double_delete.cpp -o double_delete && ./double_delete
seats 40
==…==ERROR: AddressSanitizer: attempting double-free on 0x… in thread T0:
#1 in main double_delete.cpp:7
0x… is located 0 bytes inside of 4-byte region [0x…,0x…)
freed by thread T0 here:
#1 in main double_delete.cpp:6
previously allocated by thread T0 here:
#1 in main double_delete.cpp:4
SUMMARY: AddressSanitizer: double-free double_delete.cpp:7 in main
[11 more lines of the report left out]
/bin/sh: line 1: … Abort trap: 6 ./double_delete
[exit status 134]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 double_delete_session.py
On this Mac the plain build stopped at the second delete with a trap, exit status 133, before printing done and
without a single word about why. AddressSanitizer names the bug, attempting double-free, with the stacks of the second
delete on line 7, the first one on line 6 and the allocation on line 4. A double delete usually means that two parts
of a program each believe they own the object, a question of ownership rather than of syntax.
Mistake 3: new[] released with delete
An array created with new[] must be released with delete[], and a single object with plain delete: [expr.delete]
makes every other combination undefined behaviour, and the C++ Core Guidelines repeat it as rule ES.61. With ints the
wrong form often appears to work, which is what makes this mistake persistent:
#include <print>
int main() {
int* scores = new int[3]{72, 85, 64};
std::println("first {}", scores[0]);
delete scores; // allocated with new[], so this needs delete[]
std::println("done");
} from session import run
run("""
clang++ -std=c++23 mismatch.cpp -o mismatch && ./mismatch
g++-16 -std=c++23 -Wall mismatch.cpp -o mismatch && ./mismatch
clang++ -std=c++23 -g -fsanitize=address mismatch.cpp -o mismatch 2>/dev/null && ./mismatch
ASAN_OPTIONS=alloc_dealloc_mismatch=1 ./mismatch
""") Output
$ clang++ -std=c++23 mismatch.cpp -o mismatch && ./mismatch
mismatch.cpp:6:5: warning: 'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'? [-Wmismatched-new-delete]
6 | delete scores; // allocated with new[], so this needs delete[]
| ^
| []
mismatch.cpp:4:19: note: allocated with 'new[]' here
4 | int* scores = new int[3]{72, 85, 64};
| ^
1 warning generated.
first 72
done
$ g++-16 -std=c++23 -Wall mismatch.cpp -o mismatch && ./mismatch
mismatch.cpp: In function 'int main()':
mismatch.cpp:6:12: warning: 'void operator delete(void*, std::size_t)' called on pointer returned from a mismatched allocation function [-Wmismatched-new-delete]
6 | delete scores; // allocated with new[], so this needs delete[]
| ^~~~~~
mismatch.cpp:4:40: note: returned from 'void* operator new [](std::size_t)'
4 | int* scores = new int[3]{72, 85, 64};
| ^
first 72
done
$ clang++ -std=c++23 -g -fsanitize=address mismatch.cpp -o mismatch 2>/dev/null && ./mismatch
first 72
done
$ ASAN_OPTIONS=alloc_dealloc_mismatch=1 ./mismatch
first 72
==…==ERROR: AddressSanitizer: alloc-dealloc-mismatch (operator new [] vs operator delete) on 0x…
#1 in main mismatch.cpp:6
0x… is located 0 bytes inside of 12-byte region [0x…,0x…)
allocated by thread T0 here:
#1 in main mismatch.cpp:4
SUMMARY: AddressSanitizer: alloc-dealloc-mismatch mismatch.cpp:6 in main
[9 more lines of the report left out]
[exit status 134]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 mismatch_session.py
Both compilers warn when they can see the new[] and the delete in one function: Clang by default and GCC with
-Wall, both as -Wmismatched-new-delete. Both programs then printed done anyway. The AddressSanitizer build printed
done as well, without a report, because on macOS this check is off by default: the sanitizers project documents
alloc_dealloc_mismatch as on by default except on Darwin and Windows. With ASAN_OPTIONS=alloc_dealloc_mismatch=1
the same program stops with alloc-dealloc-mismatch (operator new [] vs operator delete). When the allocation happens
in another function, as in the exercise below, neither compiler can warn, so turn that option on whenever you test with
AddressSanitizer on a Mac.
Mistake 4: forgetting delete, a leak
A leak is not undefined behaviour: the memory simply stays reserved until the program ends. For a short program that is harmless; for a server or a game that runs for days and leaks on every request or frame, memory use grows until the system has to stop it. Here the pointer to the first array is overwritten, so nothing can ever free that array:
#include <cstddef>
#include <print>
// Returns a new array of n zeros. The caller must delete[] it.
int* make_counts(std::size_t n) {
return new int[n]();
}
int main() {
int* counts = make_counts(100);
counts[7] = 3;
std::println("counts[7] = {}", counts[7]);
counts = make_counts(100); // the first array is still allocated, and now nothing points to it
delete[] counts;
} from session import run
# Leak checks on macOS: AddressSanitizer's leak detector is not supported on this Mac, and the system tool leaks is.
run("""
clang++ -std=c++23 -g -fsanitize=address leak.cpp -o leak && ASAN_OPTIONS=detect_leaks=1 ./leak
clang++ -std=c++23 -g leak.cpp -o leak && leaks -quiet -atExit -- ./leak 2>/dev/null
""") Output
$ clang++ -std=c++23 -g -fsanitize=address leak.cpp -o leak && ASAN_OPTIONS=detect_leaks=1 ./leak
==…==AddressSanitizer: detect_leaks is not supported on this platform.
/bin/sh: line 1: … Abort trap: 6 ASAN_OPTIONS=detect_leaks=1 ./leak
[exit status 134]
$ clang++ -std=c++23 -g leak.cpp -o leak && leaks -quiet -atExit -- ./leak 2>/dev/null
counts[7] = 3
Process …: 186 nodes malloced for 16 KB
Process …: 1 leak for 448 total leaked bytes.
STACK OF 1 INSTANCE OF 'ROOT LEAK: <malloc in make_counts(unsigned long)>':
5 dyld 0x… start + 6992
4 leak 0x… main + 28 leak.cpp:10
3 leak 0x… make_counts(unsigned long) + 48 leak.cpp:6
2 libc++abi.dylib 0x… operator new(unsigned long) + 52
1 libsystem_malloc.dylib 0x… _malloc + 96
0 libsystem_malloc.dylib 0x… _malloc_zone_malloc_instrumented_or_legacy + 152
====
1 (448 bytes) ROOT LEAK: <malloc in make_counts(unsigned long) 0x…> [448]
[exit status 1]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 leak_session.py
Finding leaks depends on the platform:
- Linux. AddressSanitizer includes LeakSanitizer, and Clang’s documentation says leak detection is on by default on
Linux: a program built with
-fsanitize=addressprints a leak report when it exits.-fsanitize=leakgives the leak check alone. - macOS. Clang’s documentation says leak detection can be enabled on macOS with
ASAN_OPTIONS=detect_leaks=1, but on this Apple silicon Mac the run stops withdetect_leaks is not supported on this platform. The system toolleaksworks instead:leaks -atExit -- ./programruns the program, examines its memory when it exits, and prints each block that no pointer refers to any more, with the stack where it was allocated. Here it found one leaked block of 448 bytes, the allocator’s block for the 400-byte array, created inmake_countson line 6 and called from line 10, and it exits with status 1, so a test script can fail on it.man leaksdescribes the options. - Windows. The debug C runtime of Visual Studio tracks allocations in debug builds, and a call to
_CrtDumpMemoryLeaks()before the program ends prints “Detected memory leaks!” with each block still allocated. With_CRTDBG_MAP_ALLOCand a debug version ofnew, as Microsoft’s documentation shows, each block also comes with the file and line that allocated it.
The modern replacement: owners instead of delete
Every mistake above has the same cause: a raw pointer does not know that it is responsible for an object. The C++ Core
Guidelines’ rule R.11 says to avoid calling new and delete explicitly, and R.20 says to represent ownership with
unique_ptr or shared_ptr. Here are the first program and the leak again, with owners:
#include <cstddef>
#include <memory>
#include <print>
#include <string>
#include <vector>
struct Student {
std::string name;
int marks;
Student(std::string n, int m) : name(std::move(n)), marks(m) { std::println(" Student {} created", name); }
~Student() { std::println(" Student {} destroyed", name); }
};
// n zeros, owned by the vector that is returned.
std::vector<int> make_counts(std::size_t n) { return std::vector<int>(n); }
int main() {
auto count = std::make_unique<int>(42); // owns one int
std::println("*count = {}", *count);
auto s = std::make_unique<Student>("Asha", 72); // owns one Student
s->marks += 5;
std::println("{} has {} marks", s->name, s->marks);
std::vector<int> scores(4); // owns four ints, all 0
scores.back() = 99;
std::println("scores {} {} {} {}", scores[0], scores[1], scores[2], scores[3]);
std::vector<int> counts = make_counts(100);
counts[7] = 3;
counts = make_counts(100); // the old elements are freed by the assignment
std::println("counts[7] = {}", counts[7]);
} // every owner frees what it owns: no delete anywhere from session import run
run("""
clang++ -std=c++23 -Wall -Wextra -g -fsanitize=address rewrite.cpp -o rewrite && ./rewrite
clang++ -std=c++23 -Wall -Wextra -g rewrite.cpp -o rewrite && leaks -quiet -atExit -- ./rewrite 2>/dev/null
""") Output
$ clang++ -std=c++23 -Wall -Wextra -g -fsanitize=address rewrite.cpp -o rewrite && ./rewrite *count = 42 Student Asha created Asha has 77 marks scores 0 0 0 99 counts[7] = 0 Student Asha destroyed $ clang++ -std=c++23 -Wall -Wextra -g rewrite.cpp -o rewrite && leaks -quiet -atExit -- ./rewrite 2>/dev/null *count = 42 Student Asha created Asha has 77 marks scores 0 0 0 99 counts[7] = 0 Student Asha destroyed Process …: 185 nodes malloced for 15 KB Process …: 0 leaks for 0 total leaked bytes.
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 rewrite_session.py
std::make_unique<Student>("Asha", 72) creates the object and returns a std::unique_ptr<Student> that deletes it
when the owner goes out of scope (R.23 prefers make_unique to writing new yourself). std::vector<int> scores(4)
replaces new int[4](): it owns its elements, knows its size and frees them itself. Assigning a new vector to
counts frees the old elements, so the leak of the previous section cannot happen, and leaks reports 0 leaks for 0 total leaked bytes. Student Asha destroyed now prints at the closing brace of main, where the owner s ends.
Owners also fix what no amount of care fixes by hand: when a function returns early or an exception passes through it,
a delete written at the end of the function never runs, while an owner’s destructor runs as the function is left.
Classes and RAII, and the lessons on smart pointers later in this track, show how these owners work inside. For now
the rule is: in ordinary code, store objects in containers or std::unique_ptr, and let raw pointers only observe.
Your turn: five memory bugs in a linked list
This hand-written linked list has five memory bugs. Fix them so that the program prints 4 3 2 1, 3 2 1, 3 1 and
first 3, size 2 on four lines, AddressSanitizer reports nothing with alloc_dealloc_mismatch=1, and the leak check
of your platform finds no leaks:
// A hand-written singly linked list with five memory bugs. Fix them so that the program prints
// 4 3 2 1 / 3 2 1 / 3 1 / first 3, size 2
// on four lines, AddressSanitizer reports nothing and the leak check finds no leaks.
#include <print>
struct Node {
int value;
Node* next;
};
struct List {
Node* head = nullptr;
};
void push_front(List& list, int value) {
list.head = new Node{value, list.head};
}
void pop_front(List& list) {
Node* old = list.head;
delete old;
list.head = old->next;
}
// Unlinks the first node that holds value.
void remove(List& list, int value) {
Node** link = &list.head;
while (*link != nullptr && (*link)->value != value) link = &(*link)->next;
if (*link != nullptr) *link = (*link)->next;
}
int size(const List& list) {
int n = 0;
for (const Node* p = list.head; p != nullptr; p = p->next) ++n;
return n;
}
// A new array with the values, front first. The caller frees it.
int* values(const List& list) {
int* out = new int[size(list)];
int i = 0;
for (const Node* p = list.head; p != nullptr; p = p->next) out[i++] = p->value;
return out;
}
void print(const List& list) {
for (const Node* p = list.head; p != nullptr; p = p->next) std::print("{} ", p->value);
std::println("");
}
void clear(List& list) {
for (Node* p = list.head; p != nullptr; p = p->next) delete p;
}
int main() {
List list;
for (int v : {1, 2, 3, 4}) push_front(list, v);
print(list);
pop_front(list);
print(list);
remove(list, 2);
print(list);
int* copy = values(list);
std::println("first {}, size {}", copy[0], size(list));
delete copy;
clear(list);
clear(list); // clearing an empty list again must be harmless
} As given, neither compiler warns about anything, and the first sanitizer report stops in pop_front:
from session import run
# The exercise as given: the compilers' warnings, then the first report of AddressSanitizer.
run("""
clang++ -std=c++23 -Wall -Wextra -c linked_list_exercise.cpp -o linked_list_exercise.o
g++-16 -std=c++23 -Wall -Wextra -c linked_list_exercise.cpp -o linked_list_exercise.o
clang++ -std=c++23 -g -fsanitize=address linked_list_exercise.cpp -o linked_list_exercise 2>/dev/null
ASAN_OPTIONS=alloc_dealloc_mismatch=1 ./linked_list_exercise
""", max_lines=40) Output
$ clang++ -std=c++23 -Wall -Wextra -c linked_list_exercise.cpp -o linked_list_exercise.o
$ g++-16 -std=c++23 -Wall -Wextra -c linked_list_exercise.cpp -o linked_list_exercise.o
$ clang++ -std=c++23 -g -fsanitize=address linked_list_exercise.cpp -o linked_list_exercise 2>/dev/null
$ ASAN_OPTIONS=alloc_dealloc_mismatch=1 ./linked_list_exercise
4 3 2 1
==…==ERROR: AddressSanitizer: heap-use-after-free on address 0x…
READ of size 8 at 0x… thread T0
#0 in pop_front(List&) linked_list_exercise.cpp:22
#1 in main linked_list_exercise.cpp:59
0x… is located 8 bytes inside of 16-byte region [0x…,0x…)
freed by thread T0 here:
#1 in pop_front(List&) linked_list_exercise.cpp:21
#2 in main linked_list_exercise.cpp:59
previously allocated by thread T0 here:
#1 in push_front(List&, int) linked_list_exercise.cpp:16
#2 in main linked_list_exercise.cpp:57
SUMMARY: AddressSanitizer: heap-use-after-free linked_list_exercise.cpp:22 in pop_front(List&)
[41 more lines of the report left out]
[exit status 134]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 linked_list_session.py
- Fix the bug the report names, build again and run again; each run shows the next bug.
- When AddressSanitizer is quiet, run the leak check:
leaks -atExit -- ./linked_list_exerciseon macOS, the same AddressSanitizer build on Linux. - The bugs are in
pop_front,remove,clear(two of them) andmain.
First hint: the report’s freed by stack says where the object was deleted, and the READ line says where it was used
afterwards. Read the next node’s address before you delete the node that holds it.
When it works, try the modern version: replace Node* next with std::unique_ptr<Node> next, and see which of the
five bugs can no longer be written.
Self-check
Check yourself
5 questions about this lesson. Every answer and why it is right is on the page, behind “Show the answer”. Your score stays in this browser.
Interview questions
Fresher · What is the difference between delete and delete[]?
delete p ends one object created with new and delete[] p ends an array created with new T[n]; each must be
paired with its own form, and any other combination is undefined behaviour. delete[] runs the destructor of every
element of the array, while plain delete expects a single object. The mismatch may seem to work with int, which is
why tools matter: both GCC and
Clang warn with -Wmismatched-new-delete when they see both lines, and AddressSanitizer reports it, on macOS only with
ASAN_OPTIONS=alloc_dealloc_mismatch=1. In modern code the question rarely comes up, because std::vector and
std::unique_ptr<T[]> release arrays correctly by themselves.
Key takeaways
newallocates and constructs;deletedestroys and frees. Everynewneeds exactly one matchingdelete, andnew[]needsdelete[].- Using an object after
deleteand deleting it twice are undefined behaviour; AddressSanitizer reports both with the stacks of the bad access, thedeleteand thenew. - On macOS, AddressSanitizer checks
new[]/deletemismatches only withASAN_OPTIONS=alloc_dealloc_mismatch=1, and its leak detector is not supported on Apple silicon; useleaks -atExit -- ./program. - On Linux,
-fsanitize=addressreports leaks at exit; on Windows, the CRT debug heap’s_CrtDumpMemoryLeaks()does. - Modern code lets owners free memory:
std::vectorfor arrays,std::make_uniquefor single objects, and raw pointers only to observe.
References
- Working Draft, Programming Languages: C++ (N4950), [basic.stc], [basic.stc.dynamic], [expr.new], [expr.delete] (ISO/IEC JTC1/SC22/WG21)
- AddressSanitizer (Clang documentation) (LLVM Project)
- LeakSanitizer (Clang documentation) (LLVM Project)
- AddressSanitizerFlags (sanitizers project wiki) (Google sanitizers project)
- Options Controlling C++ Dialect (-Wmismatched-new-delete) (GNU Project)
- Find memory leaks with the CRT library (Microsoft)
- Gathering information about memory use (Apple)
- C++ Core Guidelines (R.11, R.20, R.23, ES.61) (Standard C++ Foundation)
Report a problem with this lesson
Kept only in this browser. Your Learn progress