No Littering Tamu

Download as pdf or txt
Download as pdf or txt
You are on page 1of 43

No Littering!

Bjarne Stroustrup
Morgan Stanley
Columbia University, Texas A&M University
www.stroustrup.com
The big question
• “What is good modern C++?”
• Many people want to write ”Modern C++”

• Guidelines project
• https://github.com/isocpp/CppCoreGuidelines
• Produce a useful answer
• Enable many people to use that answer
• For most programmers, not just language experts
• Please help!
Stroustrup - Guidelines - CppCon'15 3
Overview
• Pointer problems
• Memory corruption
• Resource leaks
• Expensive run-time support
• Complicated code
• The solution
• Eliminate dangling pointers
• Eliminate resource leaks
• Library support for range checking and nullptr checking

No littering - Stroustrup - TAMU - March'16 4


I like pointers!
• Pointers are what the hardware offers First element One beyond the end
• Machine addresses
• For good reasons
• They are simple
• They are general
• They are fast
• They are compact
• C’s memory model has served us really well
• Sequences of objects
• But pointers are not “respectable”
• dangerous, low-level, not mathematical, …
• There is a huge ABP crowd

No littering - Stroustrup - TAMU - March'16 5


Lifetime can be messy

• An object can have


• One reference
• Multiple references
• Circular references
• No references (leaked)
• Reference after deletion (dangling pointer)
No littering - Stroustrup - TAMU - March'16 6
Ownership can be messy

static on stack on heap member

• An object can be
• on stack (automatically freed)
• on free store (must be freed)
• n static store (must never be freed)
• in another object
No littering - Stroustrup - TAMU - March'16 7
Resource management can be messy

Thread
id Lock id Lock id

Map key

• Objects are not just memory


• Sometimes, significant cleanup is needed
• File handles
• Thread handles
• Locks
• … No littering - Stroustrup - TAMU - March'16 8
Access can be messy

• Pointers can
• point outside an object (range error)
• be a nullptr ( don’t dereference)
• be unititialized (don’t dereference)

No littering - Stroustrup - TAMU - March'16 9


No littering, no leaks, no corruption
• Every object is constructed before use
• Once only
• initialized
• Every fully constructed object is destroyed
• Once only
• Every object allocated by new must be deleted
• No scoped object must be deleted (it is implicitly destroyed)
• No access through a pointer that is not pointing to an object
• Read or write
• Off the end of an object (out of range)
• To deleted object
• To “random” place in memory (e.g., uninitialized pointer)
• Through nullptr (originally: “there is no object at address zero”)
No littering - Stroustrup - TAMU - March'16 10
Current (Partial) Solutions
• Ban or seriously restrict pointers
• Add indirections everywhere
• Add checking everywhere
• Manual memory management
• Combined with manual non-memory resource management
• Garbage collectors
• Plus manual non-memory resource management
• Static analysis
• To supplement manual memory management
• “Smart” pointers
• Starting with counted pointers
• Functional Programming
No littering - Stroustrup - TAMU - March'16 11
• Eliminate pointers
Current (Partial) Solutions
• These are old problems and old solutions
• 40+ years

• Manual resource management doesn’t scale


• Smart pointers add complexity and cost
• Garbage collection is at best a partial solution
• Doesn’t handle non-memory solutions (“finalizers are evil”)
• Is expensive
• Is non-local (systems are often distributed)
• Introduces non-predictability
• Static analysis doesn’t scale
• False positives
• Dynamic linking and other dynamic phenomena
No littering - Stroustrup - TAMU - March'16 12
A solution
• Be precise about ownership
• Don’t litter
• Static guarantee
• Eliminate dangling pointers
• Static guarantee
• Make general resource management implicit
• Hide every explicit delete/destroy/close/release
• Test for nullptr and range
• Do minimal run-time checking

• There are other problems with C++ pointers


• Dealt with by other rules

No littering - Stroustrup - TAMU - March'16 13


Constraints on the solution
• I want it now
• I don’t want to invent a new language
• I don’t want to wait for a new standard
• I want it guaranteed
• “Be careful” isn’t good enough
• Don’t sacrifice
• Generality
• Performance
• Simplicity
• Portability

• Part of C++ Core Coding guidelines


• Supported by a “guidelines support library” (GSL)
• Supported by analysis tools No littering - Stroustrup - TAMU - March'16 14
No resource leaks
• We know how
• Root every object in a scope
• vector<T>
• string
• ifstream
• unique_ptr<T>
• shared_ptr<T>
• RAII
• “No naked new”
• “No naked delete”
• Constructor/destructor
• “since 1979, and still the best”

No littering - Stroustrup - TAMU - March'16 15


Dangling pointers – the worst problem
• One nasty variant of the problem
void f(X* p)
{
// …
delete p; // looks innocent enough
}

void g()
{
X* q = new X; // looks innocent enough
f(q);
// … do a lot of work here …
q->use(); // Ouch! Read/scramble random memory
} No littering - Stroustrup - TAMU - March'16 16
Dangling pointers
• We must eliminate dangling pointers
• Or type safety is compromised
• Or memory safety is compromised
• Or resource safety is compromised
• Eliminated by a combination of rules
• Distinguish owners from non-owners
• Assume raw pointers to be non-owners
• Catch every attempt for a pointer to “escape” into a scope
enclosing its owner’s scope
• return, throw, out-parameters, long-lived containers, …
• Something that holds an owner is an owner
• E.g. vector<owner<int*>>, owner<int*>[], …

No littering - Stroustrup - TAMU - March'16 17


Owners and pointers
• Every object has one owner
• An object can have many pointers to it
• No pointer can outlive the scope of the owner it points to

Call stack
Object
Object
pointer pointer

pointer owner

owner
• For an object on the free store the owner is a pointer
• For a scoped object the owner is the scope
pointer • For a member object the owner is the enclosing object
No littering - Stroustrup - TAMU - March'16 18
Dangling pointers
• Ensure that no pointer outlives the object it points to
void f(X* p)
{
// …
delete p; // bad: delete non-owner
}

void g()
{
X* q = new X; // bad: assign object to non-owner
f(q);
// … do a lot of work here …
q->use(); // Make sure we never get here
} No littering - Stroustrup - TAMU - March'16 19
How do we represent ownership?
• High-level: Use an ownership abstraction
• This is simple and preferred
• E.g., unique_ptr, shared_ptr, vector, and map
• Low-level: mark owning pointers owner
• An owner must be deleted or passed to another owner
• A non-owner may not be deleted
• This is essential in places but does not scale
• Applies to both pointers and references

• owner is intended to simplify static analysis


• owners in application code is a sign of a problem
• Usually, C-style interfaces
• “Lots of annotations” doesn’t scale
• Becomes a source of errors No littering - Stroustrup - TAMU - March'16 20
How do we represent ownership?
• Mark an owning T*: owner<T*>
• Initial idea
• Yet another kind of “smart pointer”
• owner<T*> would hold a T* and an “owner bit”
• Costly: bit manipulation
• Not ABI compatible
• Not C compatible
• So our GSL owner
• Is a handle for static analysis
• Is documentation
• Is not a type with it’s own operations
• Incurs no run-time cost (time or space)
• Is ABI compatible
• template<typename T> using owner = T;

No littering - Stroustrup - TAMU - March'16 21


GSL: owner<T>
• How do we implement ownership abstractions?
template<SemiRegular T>
class vector {
public:
// …
private:
owner<T*> elem; // the anchors the allocated memory
T* space; // just a position indicator
T* end; // just a position indicator
// …
};
• owner<T*> is just an alias for T*

No littering - Stroustrup - TAMU - March'16 22


GSL: owner<T>
• How about code we cannot change?
• ABI stability

void foo(owner<int*>); // foo requires an owner

void f(owner<int*> p, int* q, owner<int*> p2, int* q2)


{
foo(p); // OK: transfer ownership
foo(q); // bad: q is not an owner
delete p2; // necessary
delete q2; // bad: not an owner
}

• A static analysis tool can tell us where our code mishandles ownership
No littering - Stroustrup - TAMU - March'16 23
A cocktail of techniques
• Not a single neat miracle cure
• Rules (from the “Core C++ Guidelines)
• Statically enforced
• Libraries (STL, GSL)
• So that we don’t have to directly use the messy parts of C++
• Reliance on the type system
• The compiler is your friend
• Static analysis
• Essentially to extend the type system

• Each of those techniques are insufficient by itself


• Not just for C++
• But the “cocktail” relies on much of C++
No littering - Stroustrup - TAMU - March'16 24
How to avoid/catch dangling pointers
• Rules (giving pointer safety):
• Don’t transfer to pointer to a local to where it could be accessed by a caller
• A pointer passed as an argument can be passed back as a result
• A pointer obtained from new can be passed back as a result as an owner

int* f(int* p)
{
int x = 4;
return &x; // No! would point to destroyed stack frame
return new int{7}; // OK (sort of): doesn’t dangle, should return an owner<int*>
return p; // OK: came from caller
}

No littering - Stroustrup - TAMU - March'16 25


How to avoid/catch dangling pointers
• Classify pointers according to ownership
vector<int*> f(int* p)
{
int x = 4;
owner<int*> q = new int{7};
vector<int*> res = {p, &x, q}; // Bad: { unknown, pointer to local, owner }
return res;
}
• Here
• Don’t mix different ownerships in an array
• Don’t let different return statements of a function mix ownership

No littering - Stroustrup - TAMU - March'16 26


Dangling pointer summary
• Simple:
• We never let a “pointer” point to an out-of-scope object
• It’s not just pointers
• All ways of “escaping”
• return, throw, place in long-lived container, …
• Same for containers of pointers
• E.g. vector<int*>, unique_ptr<int>, iterators, built-in arrays, …
• Same for references

• Concurrency
• Keep threads alive with scoping or shared_ptr
• Apply the usual rules for a thread’s stack
• Threat another thread as just another object (it is).
No littering - Stroustrup - TAMU - March'16 27
Other problems
• Other ways of breaking the type system
• Unions: use variant
• Casts: don’t use them
• …
• Other ways of misusing pointers
• Range errors: use span<T>
• nullptr dereferencing: use not_null<T>
• Wasteful ways of addressing pointer problems
• Misuse of smart pointers
•…
• “Just test everywhere at run time” is not an acceptable answer
• We want comprehensive guidelines
No littering - Stroustrup - TAMU - March'16 28
GSL – span<T>
• Common interface style
• major source of bugs
void f(int* p, int n) // what is n? (How would a tool know?)
{
p[7] = 9; // OK?
for (int i=0; i<n; ++i) p[i] = 7; // OK?
}
• Better
void f(span<int> a)
{
a[7] = 9; // OK? Checkable against a.size()
for (int& x : a) x = 7; // OK
}

No littering - Stroustrup - TAMU - March'16 29


GSL – span<T>
• Common style • Better
void f(int* p, int n); void f(span<int> a)
int a[100]; int a[100];
// … // …
f(a,100); f(span<int>{a});
f(a,1000); // likely disaster f(a);
f({a,1000}); // easily checkable

• “Make simple things simple”


• Simpler than “old style”
• Shorter
• At least as fast

No littering - Stroustrup - TAMU - March'16 30


nullptr problems
• Mixing nullptr and pointers to objects
• Causes confusion
• Requires (systematic) checking
• Caller
void f(char*);
f(nullptr); // OK?
• Implementer
void f(char* p)
{
if (p==nullptr) // necessary?
// …
}
• Can you trust the documentation?
• Compilers don’t read manuals, or comments
• Complexity, errors, and/or run-time cost
No littering - Stroustrup - TAMU - March'16 31
GSL – not_null<T>
• Caller
void f(not_null<char*>);

f(nullptr); // Obvious error: caught be static analysis


char* p = nullptr;
f(p); // Constructor for not_null can catch the error
• Implementer
void f(not_null<char*> p)
{
// if (p==nullptr) // not necessary
// …
}

No littering - Stroustrup - TAMU - March'16 32


GSL – not_null<T>
• not_null<T>
• A simple, small class
• Should it be an alias like owner?
• not_null<T*> is T* except that it cannot hold nullptr
• Can be used as input to analyzers
• Minimize run-time checking
• Checking can be “debug only”
• For any T that can be compared to nullptr

No littering - Stroustrup - TAMU - March'16 33


To summarize
• Type and resource safety:
• RAII (scoped objects with constructors and destructors)
• No dangling pointers
• No leaks (track ownership pointers)
• Eliminate range errors
• Eliminate nullptr dereference
• That done, we attack other sources of problems
• Logic errors
• Performance bugs
• Maintenance hazards
• Verbosity
•…
No littering - Stroustrup - TAMU - March'16 34
Current state: the game is changing dramatically
• Papers
• B. Stroustrup, H. Sutter, G. Dos Reis: A brief introduction to C++'s model for type- and resource-safety.
• H. Sutter and N. MacIntosh: Preventing Leaks and Dangling
• T. Ramananandro, G. Dos Reis, X Leroy: A Mechanized Semantics for C++ Object Construction and
Destruction, with Applications to Resource Management
• Code
• https://github.com/isocpp/CppCoreGuidelines
• https://github.com/microsoft/gsl
• Static analysis: coming soon (Microsoft)
• Videos
• B. Stroustrup: : Writing Good C++ 14
• H. Sutter: Writing good C++ 14 By Default
• G. Dos Reis: Contracts for Dependable C++
• N. MacIntosh: Static analysis and C++: more than lint
• N. MacIntosh: A few good types: Evolving array_view and string_view for safe C++ code
No littering - Stroustrup - TAMU - March'16 35
C++ Information
• The C++ Foundation: www.isocpp.org
• Standards information, articles, user-group information
• Bjarne Stroustrup: www.stroustrup.com
• Publication list, C++ libraries, FAQs, etc.
• A Tour of C++: All of C++ in 180 pages
• The C++ Programming Language (4th edition): All of C++ in 1,300 pages
• Programming: Principles and Practice using C++ (2nd edition): A textbook
• The ISO C++ Standards Committee: www.open-std.org/jtc1/sc22/wg21/
• All committee documents (incl. proposals)
• Videos
• Cppcon: https://www.youtube.com/user/CppCon 2014, 2015
• Going Native: http://channel9.msdn.com/Events/GoingNative/ 2012, 2013
• Guidelines: https://github.com/isocpp/CppCoreGuidelines

Stroustrup - C++ Style -TAP'16 36


(Mis)uses of smart pointers
• “Smart pointers” are popular But ordinary pointers don’t
• To represent ownership dangle any more
• To avoid dangling pointers
• “Smart pointers” are overused
• Can be expensive
• E.g., shared_ptr
• Can mess up interfaces fore otherwise simple functions
• E.g. unique_ptr and shared_ptr
• Often, we don’t need a pointer
• Scoped objects
• We need pointers
• For OO interfaces
• When we need to change the object referred to

No littering - Stroustrup - TAMU - March'16 37


(Mis)uses of smart pointers
• Consider
• void f(T*); // use; no ownership transfer or sharing
• void f(unique_ptr<T>); // transfer unique ownership and use (uncommon style)
• void f(shared_ptr<T*>); // share ownership and use (implies cost)
• Taking a raw pointer (T*)
• Is familiar
• Is simple, general, and common
• Is cheaper than passing a smart pointer (usually)
• Doesn’t lead to dangling pointers (now!)
• Doesn’t lead to replicated versions of a function for different shared pointers
• In terms of tradeoffs with smart pointers, other simple “object designators” are
equivalent to T*
• iterators, references, span, etc.

No littering - Stroustrup - TAMU - March'16 38


No littering - Stroustrup - TAMU - March'16 40
Rules, standards, and libraries
• Could the rules be enforced by the compiler?
• Some could, but we want to use the rules now
• Some compiler support would be very nice; let’s talk
• Many could not
• Rules will change over time
• Compilers have to be more careful about false positives
• Compilers cannot ban legal code
• Could the GSL be part of the standard?
• Maybe, but we want to use it now
• The GSL is tiny and written in portable C++11
• The GSL does not depend on other libraries
• The GSL is similar to, but not identical to boost:: and experimental:: components
• So they may become standard
• We rely on the standard library
No littering - Stroustrup - TAMU - March'16 41
We are not unambitious
• Type and resource safety
• No leaks
• No dangling pointers
• No bad accesses
• No range errors
• No use of uninitialized objects
• No misuse of
• Casts
• Unions
• We think we can do it
• At scale
• 4+ million C++ Programmers, N billion lines of code
• Zero-overhead principle

No littering - Stroustrup - TAMU - March'16 42


The basic C++ model is now complete
• C++ (using the guidelines) is type safe and resource safe
• Which other language can claim that?
• Eliminate dangling pointers
• Eliminate resource leaks
• Check for range errors (optionally and cheaply)
• Check for nullptr (optionally and cheaply)
• Have concepts
• Why not a new C++-like language?
• Competing with C++ is hard
• Most attempts fail, C++ constantly improves
• It would take 10 years (at least)
• And we would still have lots of C and C++
• A new C++-like language might damage the C++ community
• Dilute support, divert resources, distract
No littering - Stroustrup - TAMU - March'16 43
To do / being done
• Implementations
• Static analysis: Microsoft (coming soon), Clang (starting), GCC (?)
• Support library (GSL):
• Technical specification
• Coding Guidelines
• Popular explanations
• Academic explanations

No littering - Stroustrup - TAMU - March'16 44


Initial work (still incomplete)
• I describe significant initial work
• Microsoft (Herb Sutter and friends)
• Morgan Stanley (Bjarne Stroustrup and friends)
• CERN (Axel Naumann and friends)
• Available
• Core guidelines (now)
• Guidelines support library (now; Microsoft, GCC, Clang; Windows, Linux, Mac)
• Analysis tool (Microsoft shipping in November; ports later (November?))
• MIT License
• Related CppCon talks (available on video)
• Herb Sutter: Writing Good C++14 By Default (focused on safety)
• Gabriel Dos Reis: Modules (fast compilation, no macro problems)
• Gabriel Dos Reis: Contracts (for documentation, run-time checking, and safety)
• Neil MacIntosh: Static analysis (no dangling pointers, no leaks)
• Neil MacIntosh: span, string_span, etc. (GSL)
No littering - Stroustrup - TAMU - March'16 45

You might also like