CppCon 2016: Herb Sutter “Leak-Freedom in C++... By Default.”

By: CppCon

675   17   70554

Uploaded on 09/26/2016


Presentation Slides, PDFs, Source Code and other presenter materials are available at: https://github.com/cppcon/cppcon2016

Lifetime safety means writing code that, by construction, is guaranteed to eliminate two things: (a) use of null/dangling pointers (including pointerlike things such as references, iterators, views, and ranges), and (b) leaks (including the rare 1% case where we’re tempted to admit the possibility of an ownership cycle or need to support lock-free concurrent data structures).

Last year, my CppCon 2015 talk “Writing Good C++14… By Default” focused on (a), null/dangling, because it's the more difficult and usually more serious problem. I gave an overview of a new approach of using static analysis rules to eliminate use of null and dangling in C++. That work continues and we’re in the process of writing down the formal rules for the approach that I showed last year.

This year, the focus will be on (b), leaks: The talk aims to begin with a set of simple rules, the “5-minute talk” to demonstrate that a handful of rules can be taught broadly to programmers of all levels, and results in code that is clean and free of leak bugs by construction.

But, since we’ll still have 85 minutes left, we can use the time to spelunk through a series of “Appendix” code examples, in which we'll demonstrate "why and how" to apply those rules to a series of increasingly complex/difficult situations, and that are aimed at increasingly advanced and “clever” (note: not always a good thing) programs and programmers. We’ll address questions such as: How should we represent Pimpl types? How should we represent trees – what should the child and parent pointer types be, and (when) should they be unique and when shared? How should we deal with “intra-module” or “encapsulated” cycles when you control all the objects in the cycle, such as all the nodes within a Graph? And what about “inter-module” or “compositional” cycles when you don’t know in advance about all the objects that could be in the cycle, such as when combining libraries written by different people in a way that may or may not respect proper layering (notoriously, using callbacks can violate layering)? The answers focus on cases where we have solid guidance, and then move toward some more experimental approaches for potentially addressing the ~1% of cases that aren’t yet well covered by unique_ptr, shared_ptr, and weak_ptr.

Herb Sutter
Software architect, Microsoft
Author, chair of the ISO C++ committee, software architect at Microsoft.

Videos Filmed & Edited by Bash Films: http://www.BashFilms.com

Comments (20):

By beached_whale    2017-09-20

Herb Sutter presented one in a talk a little while ago. https://github.com/hsutter/gcpp https://www.youtube.com/watch?v=JfmTagWcqoE

So it's totally doable in library without cost to those that do not need it.

Original Thread

By realharo    2017-09-20

>With modern C++ language features, the "complicated language with the manual memory management" a lot less obvious or necessary

Not completely though, you still have to think a lot more about ownership and object lifetimes (https://www.youtube.com/watch?v=JfmTagWcqoE), which is a lot better than manual new/delete, but still not as simple as just having a GC.

Plus you have to deal with lifetimes of objects proxied to Java code, where something in the Java code becomes the object's owner. Though you can use a bindings generator like djinni (https://github.com/dropbox/djinni) to handle this for you (with some tradeoffs).

>Debugging is only complicated on Android

It's gotten slightly better recently, but it still sucks.

With Swift it's not trivial either, it's not that easy to set breakpoints into C++ code, stack traces on crashes are often not helpful (so any unhandled C++ exception that you didn't catch and convert into a Swift error is hard to track down, etc.)

Original Thread

By pjmlp    2017-09-20

Reference counting isn't deterministic in the presence of large complex data structures.

You will know when memory gets deleted, but not how long it will take, nor how much stack space the destructors will require to run.

Enjoy Herb Sutter's "Leak-Freedom in C++... By Default." at CppCon 2016, where he explains how those issues affect C++ and goes on to implement a tracing GC.


Original Thread

By anonymous    2017-09-20

There is a talk that Herb Sutter gave at CPPCon 2016 that explains exactly how to correctly make a mark-n-sweep garbage collector in C++: Talk

Original Thread

By anonymous    2017-09-20

This is a classic problem with smart pointers and list nodes: the destructor of your node is recursive and it ends up running out of stack. This is what that stacktrace shows: stack overflow.

In CppCon 2016: Herb Sutter “Leak-Freedom in C++... By Default.” they discuss exactly this problem.

Original Thread

By anonymous    2017-09-20

Herb Sutter has a good explanation (around 3:40) https://www.youtube.com/watch?v=JfmTagWcqoE

The main advantage is that the unique pointer keeps track of how many other references there are to that pointer. You only work with the unique pointer when you are working with ownership. When you want to do something with the data with that pointer, you pass the raw pointer.

Original Thread

By anonymous    2017-09-23

https://www.youtube.com/watch?v=JfmTagWcqoE&t=1864s Go to 22:41. This is why I posted this question

Original Thread

By anonymous    2018-03-12

std::unique_ptr keeps the own of the pointed object. That means if you want to pass it as a parameter, you have to move the ownership.

Something like (note the move and &&-reference):

void addChild(std::unique_ptr<Node>&& iNode) {

Finally, I'd strongly suggest you take a look at this Herb Sutter Video. It gives some useful advice on data structures with smart pointers.

Original Thread

By anonymous    2018-03-12

Too broad for SO. But there are resources beyond SO. You can see [Herb Sutter's lecture](https://www.youtube.com/watch?v=JfmTagWcqoE) for starters. Then print and hang the poster on slide 5 for a reminder about best practices :)

Original Thread

By anonymous    2018-03-12

Herb Sutter had a great presentation a while back called leak free by design. About an hour long, but good watching. That was hard: https://www.youtube.com/watch?v=JfmTagWcqoE The stuff he goes over will save you insane amounts of debugging.

Original Thread

By anonymous    2018-03-26

See Herb Sutter's talk [*Leak-Freedom in C++... By Default*](https://www.youtube.com/watch?v=JfmTagWcqoE)

Original Thread

By anonymous    2018-04-02

I am explicitly invoking an cleanup method in order to avoid destructor recursion explosion, as pointed out in the talk: Leak-Freedom in C++... By Default by Herb Sutter given in the cppcon 2016 https://www.youtube.com/watch?v=JfmTagWcqoE (18 min :17s of the video). However, I must acknowledge that I was using the wrong function: release instead of reset.

Original Thread

By anonymous    2018-04-08

You should see [Herb Sutter's lecture](https://www.youtube.com/watch?v=JfmTagWcqoE). It should sort out the concepts nicely for you.

Original Thread

By anonymous    2018-07-02

"any other way to delete nodes from a binary tree without using new and delete?" This will take a while to get through, but Herb Sutter's got a few suggestions for you on that: https://www.youtube.com/watch?v=JfmTagWcqoE He breaks down a binary tree and explains how to do it with smart pointers.

Original Thread

By anonymous    2018-07-19

I thought it will be possible to pass the smart pointer but no!?

#include <memory>
void func(int *array){
    array[0] = 1;
int main() {
    int *array = new int[5];
    std::unique_ptr<int[]> u(new int[5]);

I spend some hours reading and watching videos about a cool thing called smart pointer. At some point I understood I can replace my pointers with the new ones, I should try unique_ptr first and if they don't get the job done then I should try shared_ptr or weak_ptr.

To reference some of it:




In code above I can do func(array); but tried func(u); and got:

$ gcc main.cpp 
main.cpp:8:2: error: no matching function for call to 'func'
main.cpp:2:6: note: candidate function not viable: no known conversion from 'std::unique_ptr<int []>' to 'int *' for 1st
void func(int *array){
1 error generated.

What's the approach to use smart pointer in this case?

Original Thread

By anonymous    2018-08-01

@Snorrlaxxx My apologies for not being clear enough in the answer linked in your question that `tail` needed to be a plain old raw pointer. [Herb Sutter's Leak Free By Design presentation.](https://www.youtube.com/watch?v=JfmTagWcqoE) Lays out a compelling case for using smart pointers, when to use them, and how to use them. Probably not the most fun hour and forty minutes in your life, but has the potential to save you far more than an hour and forty minutes over the course of a programming career. Time you can spend having fun.

Original Thread

By anonymous    2018-08-06

Yes, `unique_ptr` seems a more sane option to start. If you need a `shared_ptr` you can change to it later. Yes, a tree can be implemented with a smart pointers. Watch this https://www.youtube.com/watch?v=JfmTagWcqoE.

Original Thread

Submit Your Video

If you have some great dev videos to share, please fill out this form.