resource management in c++

51
Problem Definition Solution Practical Advices Resource Management in C++ Kirill Mendelev April 2, 2006 Kirill Mendelev Resource Management in C++

Upload: reaumur

Post on 19-Aug-2015

1.094 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Resource Management in C++

Kirill Mendelev

April 2, 2006

Kirill Mendelev Resource Management in C++

Page 2: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Outline

1 Problem Definition

2 SolutionManual ManagementAutomatic Management

3 Practical Advices

Kirill Mendelev Resource Management in C++

Page 3: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Formal definition of resource

The Pocket Oxford Dictionary

resource, n. Means of supplying what is needed, stock that can bedrawn on.

Wikipedia

A resource, also referred to as system resource, is any physical orvirtual system component of a computer system with limitedavailability.

Kirill Mendelev Resource Management in C++

Page 4: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Examples

Memory

File descriptor

Thread, process

Entity of application domain (e.g. events, messages, models)

Kirill Mendelev Resource Management in C++

Page 5: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Common treats

Limited availability

There’s only as much resources as our virtual world supplies us.

Waste management; recycling

For the virtual world to live happily every after, no garbage shouldaccumulate, non-replenishable resources should be recycled.

We take memory resource management as an object for this study,yet recommendations may be applied to any type of resource.

Kirill Mendelev Resource Management in C++

Page 6: Resource Management in C++

Problem DefinitionSolution

Practical Advices

What can go wrong

Leakage

Exhaustion

Dangling

Kirill Mendelev Resource Management in C++

Page 7: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Leak example

int triple(int val) {int* res = new int(val*3);return *res;

}

Resource is said to be leaked when it can not be accessed by anystandard mean.

Kirill Mendelev Resource Management in C++

Page 8: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Exhaustion example

int triple(int val) {static int* res = new int(val*3);return *res;

}

Exhausting algorithms never bother to dispose of their resources,while keeping references to them. Leaking and exhaustingprocesses are often mixed, for they both lead to resource depletion.

Kirill Mendelev Resource Management in C++

Page 9: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Dangling example

{...int* i = new int(2);int* j = i; // i,j are danglingdelete i; // woe to j’s users...

}

Dangling pointers reference the same place in memory, which maybe disposed of concurrently.

Kirill Mendelev Resource Management in C++

Page 10: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Another dangling example

class A {public:

void save_data(CData* a) {v.push_back(a);

}CData& operator[](int idx) {

assert(idx>=0 && idx<v.size());return *(v[idx]);

}private:

vector<CData*> v;};

Kirill Mendelev Resource Management in C++

Page 11: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Ultimate question

Ownership

Who is owner of a resource? Who creates it, who destroys it, andwhen?

Easy to ask, hard to answer. Usually, resource creator knowsnothing about resource disposer. Good old custom of passingpointers to expensive resources provides an easy way to get rid ofresource whenever we want, anyplace, anytime.

Kirill Mendelev Resource Management in C++

Page 12: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Sinful owners

Forgetful owner does not keep records of the resource

Greedy owner keeps resources forever

Egoistic owner disposes resource regardless of other customers

Spoiled owner assumes responsibility without reason

Kirill Mendelev Resource Management in C++

Page 13: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

1 Problem Definition

2 SolutionManual ManagementAutomatic Management

3 Practical Advices

Kirill Mendelev Resource Management in C++

Page 14: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

Behave!

Law and order

Coding guidelines and design techniques may reduce amount offaulty places, if followed strictly and frequent review sessions areapplied, so to enforce the rules.

Example of such rule

Every resource should be allocated in object’s constructor,deallocated in object’s destructor. No reference to resource may bereturned from object.

Programmers, being artists, hate rules and love to break themwhenever policemen are not around there.

Kirill Mendelev Resource Management in C++

Page 15: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

Common sense

Do it accurately

Chose owners thoughtfully, do not pass ownership, keep the wholesystem in mind, so no pointer gets left behind. Or forgotten.

This works well for small systems, which are rarely extended.Expect newly added parts to wreak havoc, for this approach doesnot constrain the developer to follow the original resourcemanagement policy.

Kirill Mendelev Resource Management in C++

Page 16: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

Where common sense does not help

int f() {int* i = new int(-2);int j = sqrt(*i); // exception throwndelete i;return j;

}

“throw” clauses are optional in C++, so we have no guaranteedway to protect ourselves from exceptions thrown by third parties.

Kirill Mendelev Resource Management in C++

Page 17: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

Management decision

Centralize everything

Create a number of “manager” classes, which will be the only wayof accessing a resource. Manager is the only owner of the object.

This way, no resource will ever be leaked, yet exhaustion ispossible. Dangling is possible, but not likely. Biggest problem israces between thread-users, which create a different class ofproblems. Besides, resource-management classes lead to tightcoupling in designs.

Kirill Mendelev Resource Management in C++

Page 18: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

Only cowards are afraid of leaks

Let it leak

Fortunately, major operation systems take care of resourcecollection in a per-process basis. It is, all the system-wide resourcesallocated by process are properly disposed of upon processtermination. If the task is known to live a short, yet bright life, itmay just accept resource leakage.

Well suited for small utilities, which should be used every once in awhile. OTOH, “Apache” web server kills its children from time totime, when the memory consumption seem to grow beyond control.

Kirill Mendelev Resource Management in C++

Page 19: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

Failure is not an option

Think totalitarian. “1984”, George Orwell.

The purpose of Newspeak was not only to provide amedium of expression for the world-view and mentalhabits proper to the devotees of Ingsoc, but to make allother modes of thought impossible.

C++ is a language flexible enough to be modified to make theresource mismanagement hard, if not impossible.

Kirill Mendelev Resource Management in C++

Page 20: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

Smart Pointers

Overloading certain operators, we can mimic pointer.

struct Nat {int n;string what() { stringstream s; s << n; return s.str() }

};class NatP {public:

NatP() { num.n = 1; }Nat& operator*() { return num; }NatP* operator->() { return &num; }NatP& operator++() { ++num.n; return *this; }

private:Nat num;

};

Kirill Mendelev Resource Management in C++

Page 21: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

Smart Pointers – contd.

void show_all() {NatP n;while(1) {

cout << n->what() << endl;++n;

}}

It’s easy to add a null-pointer semantics to these pseudo-pointers,so ultimately and seamlessly, we can replace native pointers bysophisticated classes.

Kirill Mendelev Resource Management in C++

Page 22: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

RAII

Resource Acquisition is Initialization

Resource is acquired in constructor and is destroyed in destructor.

struct StrongInt {StrongInt(int n) { num_ptr = new int(n); }~StrongInt() { delete num_ptr; }int& operator*() { return *num_ptr; }int* num_ptr;

};int thrice(int n) {

StrongInt strong_ptr(n*3);return *strong_ptr;

}

Kirill Mendelev Resource Management in C++

Page 23: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

Value semantics

C++ employs call-by-value semantics to pass arguments inside offunctions, unless references are used. RAII-oriented classes will becreated and destroyed when passing scopes.

StrongInt thrice(StrongInt strong_ptr) {StrongInt result((*strong_ptr) * 3);return result;

}

Obviously, a disaster. Solution will add a “ownership” flag,redefine copy-constructor, assignment operator and check this flagin destructor. Quite a work.

Kirill Mendelev Resource Management in C++

Page 24: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

STL and auto ptr

auto_ptr template provided by STL is a simplest strong pointerwith RAII semantics and primitive ownership control.

auto_ptr<int> thrice(auto_ptr<int> auto_int) {auto_ptr<int> ap(new int(*auto_int*3));return ap;

}

Kirill Mendelev Resource Management in C++

Page 25: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

Deficiencies of auto ptr

Only one owner, so no sharing of resources

BigData* data = new BigData;auto_ptr<BigData> ap1(data);auto_ptr<BigData> ap2(data);

Ignores OO, denying “is a” relationship

auto ptr<Base> f(){return auto_ptr<Derived>(new Derived);

}

Copies are not equivalent, so forget about containers

vector<auto_ptr<int> > v;

Kirill Mendelev Resource Management in C++

Page 26: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

Deficiencies of auto ptr

Only one owner, so no sharing of resources

BigData* data = new BigData;auto_ptr<BigData> ap1(data);auto_ptr<BigData> ap2(data);

Ignores OO, denying “is a” relationship

auto ptr<Base> f(){return auto_ptr<Derived>(new Derived);

}

Copies are not equivalent, so forget about containers

vector<auto_ptr<int> > v;

Kirill Mendelev Resource Management in C++

Page 27: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

Deficiencies of auto ptr

Only one owner, so no sharing of resources

BigData* data = new BigData;auto_ptr<BigData> ap1(data);auto_ptr<BigData> ap2(data);

Ignores OO, denying “is a” relationship

auto ptr<Base> f(){return auto_ptr<Derived>(new Derived);

}

Copies are not equivalent, so forget about containers

vector<auto_ptr<int> > v;

Kirill Mendelev Resource Management in C++

Page 28: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

Reference counting

Auto ptr is a simplest RC

auto_ptr is an example of so-called “reference counting” garbagecollection. We wrap the shared resource in a class, which countsnumber of times anyone from outside required reference to innerobject. Once this counter reaches zero, nobody uses us anymoreand the inner object has to be reclaimed.

Patented extensions

Simple extension to auto_ptr, adding multiple owners, solves firstand last problems, yet the OO issue is yet to be addressed.

Kirill Mendelev Resource Management in C++

Page 29: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

Private inheritance and reference counting

C++ as multi-paradigm language

C++ is not strictly object-oriented language, and the templateswe’ve used to create reference counters belong to “generic”paradigm whatsoever.

“Bridge” between generic and OO paradigms

C++ provides “private” inheritance to answer “implemented interms of” kind of relationship. Privately inherited class, then, maytake advantage of outer inheritance to store in itself polymorphicdata.

Kirill Mendelev Resource Management in C++

Page 30: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

Inherit a template

struct Human_I {virtual void play() = 0;

};class Boy : public Human_I {virtual void play();

};class Girl : public Human_I {virtual void play();

};

template<class T, class I>class RefCounted {public:

// RC operatorsT* ptr() { return rep; }

private:T* rep;I* count;static RefCounted nil;

};

Kirill Mendelev Resource Management in C++

Page 31: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

Polymorphism by value

class Human : private RefCounted<Human_I,int> {public:

Human(Human_I* inst) : base(inst) {}Human() {}void play() {

ptr()->play(); // ptr defined in RefCounted}

}

Kirill Mendelev Resource Management in C++

Page 32: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

Polymorphism by value – contd.

void perform(Human person) {person.play();

}int main(int, char**) {

Human adam = new Boy;Human eve = new Girl;perform(adam);perform(eve);

}

Kirill Mendelev Resource Management in C++

Page 33: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

Transition from RC to GC

This page is intentionally left blank.

Kirill Mendelev Resource Management in C++

Page 34: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

Garbage collectors

Aim

Garbage collecting languages save developers from the task ofmemory deallocation, so solving both memory leaking and danglingpointers problems. Memory exhaustion still may happen.

Strategy

Garbage collecting (GC) algorithms produce a transitive closure ofmemory blocks accessible from stack memory. Unneeded memoryis then reclaimed and reused. Most GCs can not be adapted tomanagement of resources other than memory.

Kirill Mendelev Resource Management in C++

Page 35: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

GC efficiency

GCs have a long history of claimed and proved inefficiency.Though recent development in GC theory and practice renderedthem to be efficient enough to be used in real-time applications.Now, application should prove that its performance requirementsare high enough to forfeit usage of GC.

Kirill Mendelev Resource Management in C++

Page 36: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

GC and C++

Why no standard GC in C++

There’s no firm understanding of the proper GC technique, whichshould be implemented by all vendors of C++.

Is it possible to use GC with C++

Yes, Boehm GC is a conservative, “internal pointers”, non-movingmark-and-sweep collector, which can be easily plugged into existingC++ program.

How it came, Holmes?

Elementary, my dear Watson. They overrode malloc and free.

Kirill Mendelev Resource Management in C++

Page 37: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

Boehm GC algorithm

1 Mark all the objects on stack as “reachable”

2 Mark all the objects reachable from “reachables” as also“reachable”

3 Repeat step 2 until no more objects found

4 Reuse unmarked objects (sweep)

How do we know one object is reachable from another? If oneobject contains something that looks like a pointer, it is treated asa pointer. So, we’ve got small chance we’ll be confused by somecomplex integers, and some memory will be marked as “reachable”even though it is not.

Kirill Mendelev Resource Management in C++

Page 38: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

Boehm GC and C++

int main(int, char**) {for(int i=0;;++i)

int* j = new int(i % 2);}

Leaks if compiled as

> gcc -o leak leak.cc

Does not leak if GC substitutes standard system “malloc”

> gcc -o leak leak.cc /usr/local/lib/libgc.a

Kirill Mendelev Resource Management in C++

Page 39: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Manual ManagementAutomatic Management

Threads, system allocators, proprietary allocators

Boehm GC is thread-safe

Boehm GC can be used selectively, yet care should be takennot to store pointers to gc-allocated memory within objectsproduced by non-gc allocators

Boehm GC is cross-platform

Kirill Mendelev Resource Management in C++

Page 40: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Plan your dive, dive your plan

Resource management is a design decision

Decision on resource management should be taken along withother design decisions. It is as hard to change the managementscheme from “accurately delete unneeded objects” to “useauto_ptr when needed” as to switch from data-driven design toevent-driven design.

Find resources early

Ask yourself: “what happens if this stuff is not finalized? Am Igoing to get out of stock of these eventually”? Major logic entitiesof design are usually resources.

Kirill Mendelev Resource Management in C++

Page 41: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Checklist

1 Does your application live long enough to exhaust resource?

No: use “allocate once, never deallocate” scheme

2 Can you promise a solitary ownership at any moment?Yes: use auto ptr

3 Can you sacrifice simple OO for value-semantics?Yes: use reference countersNo: think again

4 Is it memory you’re worrying about?Yes: seriously consider using Boehm GC

5 If nothing else helps, split task to subtasks and start from thebeginning

Kirill Mendelev Resource Management in C++

Page 42: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Checklist

1 Does your application live long enough to exhaust resource?No: use “allocate once, never deallocate” scheme

2 Can you promise a solitary ownership at any moment?Yes: use auto ptr

3 Can you sacrifice simple OO for value-semantics?Yes: use reference countersNo: think again

4 Is it memory you’re worrying about?Yes: seriously consider using Boehm GC

5 If nothing else helps, split task to subtasks and start from thebeginning

Kirill Mendelev Resource Management in C++

Page 43: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Checklist

1 Does your application live long enough to exhaust resource?No: use “allocate once, never deallocate” scheme

2 Can you promise a solitary ownership at any moment?

Yes: use auto ptr

3 Can you sacrifice simple OO for value-semantics?Yes: use reference countersNo: think again

4 Is it memory you’re worrying about?Yes: seriously consider using Boehm GC

5 If nothing else helps, split task to subtasks and start from thebeginning

Kirill Mendelev Resource Management in C++

Page 44: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Checklist

1 Does your application live long enough to exhaust resource?No: use “allocate once, never deallocate” scheme

2 Can you promise a solitary ownership at any moment?Yes: use auto ptr

3 Can you sacrifice simple OO for value-semantics?Yes: use reference countersNo: think again

4 Is it memory you’re worrying about?Yes: seriously consider using Boehm GC

5 If nothing else helps, split task to subtasks and start from thebeginning

Kirill Mendelev Resource Management in C++

Page 45: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Checklist

1 Does your application live long enough to exhaust resource?No: use “allocate once, never deallocate” scheme

2 Can you promise a solitary ownership at any moment?Yes: use auto ptr

3 Can you sacrifice simple OO for value-semantics?

Yes: use reference countersNo: think again

4 Is it memory you’re worrying about?Yes: seriously consider using Boehm GC

5 If nothing else helps, split task to subtasks and start from thebeginning

Kirill Mendelev Resource Management in C++

Page 46: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Checklist

1 Does your application live long enough to exhaust resource?No: use “allocate once, never deallocate” scheme

2 Can you promise a solitary ownership at any moment?Yes: use auto ptr

3 Can you sacrifice simple OO for value-semantics?Yes: use reference counters

No: think again

4 Is it memory you’re worrying about?Yes: seriously consider using Boehm GC

5 If nothing else helps, split task to subtasks and start from thebeginning

Kirill Mendelev Resource Management in C++

Page 47: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Checklist

1 Does your application live long enough to exhaust resource?No: use “allocate once, never deallocate” scheme

2 Can you promise a solitary ownership at any moment?Yes: use auto ptr

3 Can you sacrifice simple OO for value-semantics?Yes: use reference countersNo: think again

4 Is it memory you’re worrying about?Yes: seriously consider using Boehm GC

5 If nothing else helps, split task to subtasks and start from thebeginning

Kirill Mendelev Resource Management in C++

Page 48: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Checklist

1 Does your application live long enough to exhaust resource?No: use “allocate once, never deallocate” scheme

2 Can you promise a solitary ownership at any moment?Yes: use auto ptr

3 Can you sacrifice simple OO for value-semantics?Yes: use reference countersNo: think again

4 Is it memory you’re worrying about?

Yes: seriously consider using Boehm GC

5 If nothing else helps, split task to subtasks and start from thebeginning

Kirill Mendelev Resource Management in C++

Page 49: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Checklist

1 Does your application live long enough to exhaust resource?No: use “allocate once, never deallocate” scheme

2 Can you promise a solitary ownership at any moment?Yes: use auto ptr

3 Can you sacrifice simple OO for value-semantics?Yes: use reference countersNo: think again

4 Is it memory you’re worrying about?Yes: seriously consider using Boehm GC

5 If nothing else helps, split task to subtasks and start from thebeginning

Kirill Mendelev Resource Management in C++

Page 50: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Checklist

1 Does your application live long enough to exhaust resource?No: use “allocate once, never deallocate” scheme

2 Can you promise a solitary ownership at any moment?Yes: use auto ptr

3 Can you sacrifice simple OO for value-semantics?Yes: use reference countersNo: think again

4 Is it memory you’re worrying about?Yes: seriously consider using Boehm GC

5 If nothing else helps, split task to subtasks and start from thebeginning

Kirill Mendelev Resource Management in C++

Page 51: Resource Management in C++

Problem DefinitionSolution

Practical Advices

Further reading

“The Design and Evolution of C++”, Bjarne Stroustrup

“The C++ Programming Language”, Bjarne Stroustrup

http://www.hpl.hp.com/personal/Hans Boehm/gc/

http://www.research.att.com/˜bs/JSF-AV-rules.pdf

Kirill Mendelev Resource Management in C++