I am having a hard time wrapping around knowing when to use pointers vs references. My question is: in Java/C# you can pass an object as an argument to a function and then assign this argument to an internal class variable so that you can use it outside the scope of the method later on. However, in C++ I am not sure how to achieve the same thing. If I pass by reference, I can only use it within the scope of that method. If I assign the reference to an internal variable of the same type, changes on one don't affect the other. I cannot declare an uninitialized reference either (maybe through constructor). The only solutions I have found are to either pass in the reference every time I need to work with it (as an argument) or pass in a pointer instead once (e.g. through a constructor) and convert it to a reference every time I need to use it outside the scope.
Here is an example method I have for testing this:
initially the value referenced by get and setValue is set to zero.
I call Controller2.initialize(Controller &controller, Controller *controllerPtr)
I call Controller2::process(Controller &controller)
The output is shown after the code blocks below
#include "Controller2.h"
Controller2::Controller2()
{
}
void Controller2::initialize(Controller &controller, Controller *controllerPtr)
{
_controller = controller;
_controllerPtr = controllerPtr;
Controller &controllerRef = *_controllerPtr;
controller.setValue(5);
Serial.println("");
Serial.print("_Controller in initialize(): ");
Serial.print(_controller.getValue());
Serial.print(" Controller in initialize(): ");
Serial.print(controller.getValue());
Serial.print(" Controller Ptr in initialize(): ");
Serial.print(controllerRef.getValue());
Serial.println();
}
void Controller2::process(Controller &controller)
{
Serial.println("");
Serial.print("_Controller in process(): ");
Serial.print(_controller.getValue());
Serial.print(" Controller in process(): ");
Serial.print(controller.getValue());
Controller &controllerRef = *_controllerPtr;
Serial.print(" Controller Ptr in process(): ");
Serial.print(controllerRef.getValue());
Serial.println();
}
Controller2.h:
#include "Arduino.h"
#include "Controller.h"
#ifndef Controller2_h
#define Controller2_h
class Controller2
{
public:
Controller2();
void initialize(Controller &controller, Controller* controllerPtr);
void manage();
void process(Controller &controller);
private:
Controller _controller;
Controller* _controllerPtr;
};
#endif
Controller Class:
#include "Controller.h"
Controller::Controller()
{
}
void Controller::initialize()
{
}
void Controller::setValue(int val)
{
value = val;
}
int Controller::getValue()
{
return value;
}
Controller.h:
#include "Arduino.h"
#ifndef Controller_h
#define Controller_h
class Controller
{
public:
Controller();
void initialize();
void manage();
void setValue(int val);
int getValue();
private:
int value = 0;
};
#endif
And the main class:
#include <Arduino.h>
#include <Controller.h>
#include <Controller2.h>
Controller controller;
Controller2 controller2;
void setup()
{
Serial.begin(115200);
Serial.println("");
Serial.print("Controller initial: ");
Serial.print(controller.getValue());
Serial.println();
controller2.initialize(controller, &controller);
controller2.process(controller);
}
void loop()
{
}
The output results in:
Controller initial: 0
_Controller in initialize(): 0 Controller in initialize(): 5 Controller Ptr in initialize(): 5
_Controller in process(): 0 Controller in process(): 5 Controller Ptr in process(): 5
Is this correct or am I missing something here?
The truth is that C++ references behave in many ways like pointers, without the pointer-specific syntax. For both pointers and references you have the pointer/reference-to-an-object and then you have the object itself, and the lifetime of the pointer/reference can differ from the lifetime of the object that it points-to/references, so in cases where the pointer/reference outlives the object, you have to be very careful not to dereference the pointer/reference after the object has been destroyed, or else you'll invoke undefined behavior and your program won't behave well.
So for example this is valid:
class Controller2
{
public:
Controller2(Controller & controllerRef)
: _controllerRef(controllerRef)
{/*empty*/}
private:
Controller & _controllerRef;
};
... and behaves much the same as the pointer-based implementation:
class Controller2
{
public:
Controller2(ControllerPtr * controllerPtr)
: _controllerPtr(controllerPtr)
{/*empty*/}
private:
Controller * _controllerPtr;
};
... the main difference being that in the reference-based implementation, there is no (legal) way for the user to pass in a NULL reference to the Controller2 constructor, therefore your code doesn't have to worry about checking _controllerRef to see if it's NULL, since the language guarantees it won't be NULL (or to be more specific, it says that if the reference is NULL, then the program is already broken beyond repair, so you can assume it isn't NULL).
In both cases, passing a raw-pointer/reference to an external object is a bit risky, so unless you have some other way to guarantee that the pointed-to/referenced object will outlive any possible dereferencing of _controllerRef, you might be better off either making a private copy of the object, or if that isn't practical, using something like a shared_ptr or unique_ptr instead to guarantee that the referenced object won't be destroyed until after you've stopped holding any references to it.
Try to start thinking of things in terms of ownership of the memory. C++ doesn't have a garbage collector, so it's your job to manage who owns what memory.
Normally, the owner of the memory maintains the actual memory itself, or in the case of large (or virtual) data, maintains a std::unique_ptr to it. std::unique_ptr is just like a raw pointer except that it enforces (a) the memory is cleaned up when you're done with it, and (b) there's only one unique pointer to the data at a given moment.
If you need to let someone borrow the data (i.e. let a function do something with it), then you pass a reference. MyClass& is a type that looks at someone else's MyClass instance and might modify it. const MyClass& is a type that looks at someone else's MyClass and doesn't modify it (for obvious reasons, you should default to the latter unless mutability is required).
If you need a value to have multiple owners, then first think about whether you really need it. Lots of things fit into the single-ownership model, and generally with some minor restructuring you can get by just fine with references and unique pointers. But if you really need multi-ownership, you can use std::shared_ptr and std::weak_ptr to get that behavior (strong vs. weak references; you can read more about the difference at those links). But this should be the exception rather than the norm.
You should use raw pointers (i.e. MyClass*) almost never. In fact, as a C++ beginner, you should use raw pointers literally never. For collections, use std::vector, not a raw array that decays to a pointer (there are reasons to use the latter, but those are technical and only serve to confuse when just starting out). For individual data, use single- or multi- ownership as discussed above. If you write MyClass* somewhere, you should be able to replace it with a reference or a smart pointer (unique, shared, or weak). If you write new or delete somewhere, you should be able to replace it with a smart pointer constructor or simple value allocation (lots of Java devs coming to C++ find themselves writing MyClass* x = new MyClass() when MyClass x{} will do just fine).
My last major C++ project was a 13kloc programming language interpreter, and I used exactly one raw pointer in it (I remember specifically when I made this concession), to implement an obscure optimization trick in a critical path. There is a paragraph and a half of comments around that explaining why I had to do it and who actually owns the memory, since the type no longer communicates that information. Everything else was references and smart pointers. When you get the hang of it, you almost never need actual raw pointers.
Finally, a couple of pieces of advice.
Java and C# rely heavily on null. Try to avoid nullptr / NULL in C++. If you want a value that may or may not exist, std::optional is the idiomatic way to do it (if you don't have access to C++17, Boost has a header-only library to do the same). In particular, you should never make a value into a pointer for the sole purpose of allowing nullptr; that's what std::optional was designed specifically to do.
You may run into some really old code or tutorials online that use std::auto_ptr. Do not use this type. std::unique_ptr does everything it does better. std::auto_ptr is a broken implementation and should never be used.
The other answers give the C++ perspective. To give you a starting point, as you come from a Java/C# perspective:
A variable that holds an object in Java (or C#) corresponds roughly to a variable that holds a shared_ptr in C++. There are differences, so don't expect that you should (or even can) simply "think Java" and use a shared_ptr. (You should "think C++" when coding in C++, just like you should "think Java" when coding in Java.) However, when comparing Java code and C++ code, thinking of Java objects as C++ shared pointers covers the 80% case. This should help you catch yourself when you try to apply semantics from another language (Java or C#) to C++ code.
Some additional reading:
What is a smart pointer and when should I use one?
What are the differences between a pointer variable and a reference variable in C++?
Even though you asked about "pass by" (implying function parameters), the real issue behind your symptom appears to be the _controller member. This is neither a reference nor a pointer; it is an object. Each Controller2 object has a Controller object as a member. The number of Controller objects will be at least the number of Controller2 objects. These are not shared. The line _controller = controller; does not make _controller refer to the same object as controller. No, it copies values to _controller from controller, the same way that assigning int variables copies a value.
One way to see this is to add a line to your code:
controller.setValue(5); \\ existing line, affects parameter
_controller.setValue(20); \\ new line, affects member
This gives your two Controller objects values that are distinct from each other, and distinct from the initial value. (The two Controller objects are the global variable named controller and the _controller member of the global variable named controller2.)
Some additional reading:
Should I prefer pointers or references in member data?
Related
I'm trying to implement the Observer pattern, but i don't want observers being responsible for my program safety by maintaining the reference list in ObservableSubject.
Meaning that when the Observer object lifetime ends, I dont want to explicitly call ObservervableSubject::removeObserver(&object).
I have come up with an idea to use use pointer references in ObservableSubject.
My question are: Is implementation described above and attempted below possible?
And what is happening in my program, how do i prevent dereferencing trash?
Apriori excuse: This is an attempt at understanding C++, not something that should have actual use or be prefered over other implementations.
My solution attempt:
// Example program
#include <iostream>
#include <string>
#include <vector>
class ObserverInterface {
public:
virtual ~ObserverInterface() {};
virtual void handleMessage() = 0;
};
class ObservableSubject
{
std::vector<std::reference_wrapper<ObserverInterface*>> listeners;
public:
void addObserver(ObserverInterface* obs)
{
if (&obs)
{
// is this a reference to the copied ptr?
// still, why doesnt my guard in notify protect me
this->listeners.push_back(obs);
}
}
void removeObserver(ObserverInterface* obs)
{
// todo
}
void notify()
{
for (ObserverInterface* listener : this->listeners)
{
if (listener)
{
listener->handleMessage();
}
}
}
};
class ConcreteObserver : public ObserverInterface {
void handleMessage()
{
std::cout << "ConcreteObserver: I'm doing work..." << std::endl;
}
};
int main()
{
ObservableSubject o;
{
ConcreteObserver c;
o.addListener(&c);
}
o.notify();
std::cin.get();
}
Line in ObservableSubject::notify() : Listener->handleMessage() throws the following exception:
Exception thrown: read access violation.
listener->**** was 0xD8BF48B. occurred
Your program has undefined behavior.
ObservableSubject o;
{
ConcreteObserver c;
o.addListener(&c); // Problem
}
c gets destructed when the scope ends. You end up storing a stale pointer in the list of listeners of o.
You can resolve the problem by defining c in the same scope as o or by using dynamically allocated memory.
ObservableSubject o;
ConcreteObserver c;
o.addListener(&c);
or
ObservableSubject o;
{
ConcreteObserver* c = new ConcreteObserver;
o.addListener(c);
}
When you use dynamically allocated memory, the additional scope is not useful. You might as well not use it.
ObservableSubject o;
ConcreteObserver* c = new ConcreteObserver;
o.addListener(c);
If you choose to use the second approach, make sure to deallocate the memory. You need to add
delete c;
before the end of the function.
Update, in response to OP's comment
You said:
Maybe i wasn't clear. Solving the lifetime/stale pointer problem was the intention of my solution. I know i have no problems if i have properly managed lifetime, or if i add detachObserver option on Observer destruction. I want to somehow be able to tell from the ObservableSubject if his list of Observers was corrupted, without the Observer explicitly telling that.
Since dereferencing an invalid pointer is cause for undefined behavior, it is essential that you track the lifetime of observers and make sure to update the list of observers when necessary. Without that, you are courting undefined behavior.
Note, I don't recommend the following approach, but I think it meets your requirements. You have a duplicated observer list. One is under control of the Observers, and the other, using weak pointers, is handled by the Observable object.
Make the Observer constructors private and use an ObserverFactory (which is their friend) to obtain a std::shared_ptr<Observer>. The factory has a map from raw pointers to reference wrappers to the associated shared pointer.
The listeners list becomes std::vector<std::weak_ptr<Observer>>. On list traversal, you try to lock the weak_ptr; if it succeeds, handle the message; if it fails, that is, you get nullptr, remove the weak pointer from the list.
When the listener no longer wants to listen, it tells the Factory to do a reset on its shared pointer and remove from the map. This step is rather ugly, as it is just a fancy delete this, normally a code smell.
I believe you can also do this with std::shared_from_this.
The plan is you move the maintenance away from the ObservableSubject back into the Observers.
// is this a reference to the copied ptr?
Yes, it is. It invokes undefined behaviour because the obs pointer variable goes out of scope at the end of the function, resulting in a dangling reference.
The whole idea doesn’t gain you anything. Even if you make the ref-to-pointer approach work correctly, you are depending on one thing: That that exact pointer variable is set to nullptr once the object dies. Essentially that’s the same problem as ensuring that no dangling pointers are held in listeners.
For a heap object: How do you make sure that nobody deletes the object through a different pointer? Or forgets to null the registered pointer? It’s even worse for stack objects like in your example. The object goes out of scope and dies automatically. There is no opportunity to null anything unless you introduce an additional pointer variable that you’d have to manage manually.
You could consider two general alternatives to your approach:
Make the relation bidirectional. Then whoever dies first (observable or observer) can notify the other party abouts its death in the destructor.
If you don’t like the bidirectionality a central, all-knowing orchestrator that decouples oberservers and observables works, too. Of course that introduces some kind of global state.
Real-life implementations usually go in the general direction of leveraging C++ destructors for deregistration. Have a look at Qt’s signal/slot mechanism, for example.
I have some code that currently uses raw pointers, and I want to change to smart pointers. This helps cleanup the code in various ways. Anyway, I have factory methods that return objects and its the caller's responsibility to manager them. Ownership isn't shared and so I figure unique_ptr would be suitable. The objects I return generally all derive from a single base class, Object.
For example,
class Object { ... };
class Number : public Object { ... };
class String : public Object { ... };
std::unique_ptr<Number> State::NewNumber(double value)
{
return std::unique_ptr<Number>(new Number(this, value));
}
std::unique_ptr<String> State::NewString(const char* value)
{
return std::unique_ptr<String>(new String(this, value));
}
The objects returned quite often need to be passed to another function, which operates on objects of type Object (the base class). Without any smart pointers the code is like this.
void Push(const Object* object) { ... } // push simply pushes the value contained by object onto a stack, which makes a copy of the value
Number* number = NewNumber(5);
Push(number);
When converting this code to use unique_ptrs I've run into issues with polymorphism. Initially I decided to simply change the definition of Push to use unique_ptrs too, but this generates compile errors when trying to use derived types. I could allocate objects as the base type, like
std::unique_ptr<Object> number = NewNumber(5);
and pass those to Push - which of course works. However I often need to call methods on the derived type. In the end I decided to make Push operate on a pointer to the object stored by the unique_ptr.
void Push(const Object* object) { ... }
std::unique_ptr<Object> number = NewNumber(5);
Push(number.get());
Now, to the reason for posting. I'm wanting to know if this is the normal way to solve the problem I had? Is it better to have Push operate on the unique_ptr vs the object itself? If so how does one solve the polymorphism issues? I would assume that simply casting the ptrs wouldn't work. Is it common to need to get the underlying pointer from a smart pointer?
Thanks, sorry if the question isn't clear (just let me know).
edit: I think my Push function was a bit ambiguous. It makes a copy of the underlying value and doesn't actually modify, nor store, the input object.
Initially I decided to simply change the definition of Push to use
unique_ptrs too, but this generates compile errors when trying to use
derived types.
You likely did not correctly deal with uniqueness.
void push(std::unique_ptr<int>);
int main() {
std::unique_ptr<int> i;
push(i); // Illegal: tries to copy i.
}
If this compiled, it would trivially break the invariant of unique_ptr, that only one unique_ptr owns an object, because both i and the local argument in push would own that int, so it is illegal. unique_ptr is move only, it's not copyable. It has nothing to do with derived to base conversion, which unique_ptr handles completely correctly.
If push owns the object, then use std::move to move it there. If it doesn't, then use a raw pointer or reference, because that's what you use for a non-owning alias.
Well, if your functions operate on the (pointed to) object itself and don't need its address, neither take any ownership, and, as I guess, always need a valid object (fail when passed a nullptr), why do they take pointers at all?
Do it properly and make them take references:
void Push(const Object& object) { ... }
Then the calling code looks exactly the same for raw and smart pointers:
auto number = NewNumber(5);
Push(*number);
EDIT: But of course no matter if using references or pointers, don't make Push take a std::unique_ptr if it doesn't take ownership of the passed object (which would make it steal the ownership from the passed pointer). Or in general don't use owning pointers when the pointed to object is not to be owned, std::shared_ptr isn't anything different in this regard and is as worse a choice as a std::unique_ptr for Push's parameter if there is no ownership to be taken by Push.
If Push does not take owenrship, it should probably take reference instead of pointer. And most probably a const one. So you'll have
Push(*number);
Now that's obviously only valid if Push isn't going to keep the pointer anywhere past it's return. If it does I suspect you should try to rethink the ownership first.
Here's a polymorphism example using unique pointer:
vector<unique_ptr<ICreature>> creatures;
creatures.emplace_back(new Human);
creatures.emplace_back(new Fish);
unique_ptr<vector<string>> pLog(new vector<string>());
for each (auto& creature in creatures)
{
auto state = creature->Move(*pLog);
}
I am trying to print on which line addref and release is called.Here is code
In code below I have created on ReferenceCount class whose main functionality to increase and decrease refernce count.
Referencemanager class keeps track of reference count and deletes the object once it reaches 0.
Test1 is test class .In main I am creating Test1 pointer and wrapping it with CReferenceManager class. Now during creation of CReferenceManager class AddRef is called and while destruction Release would be called.
If there is memory leak then it would be easier to detect if I can print out FILE and LINE numbers when AddRef and Release called with reference counts at that point.
If there a way that I can print FILE and LINE number from where AddRef and Release gets called. One way is that I can overwrite AddRef and Release in derived classes and prinf FILE and LINE numbers
//ReferenceCount.h
#include <string>
#include <Windows.h>
using namespace std;
class CReferenceCount
{
public:
CReferenceCount();
virtual ~CReferenceCount();
virtual void AddRef();
virtual bool Release();
private:
LONG m_ref;
};
// RefCount.cpp
//
#include "stdafx.h"
#include "ReferenceCount.h"
CReferenceCount::CReferenceCount():m_ref(0)
{
AddRef();
}
CReferenceCount::~CReferenceCount()
{
}
void CReferenceCount::AddRef()
{
InterlockedIncrement(&m_ref);
}
bool CReferenceCount::Release()
{
if (InterlockedDecrement(&m_ref) == 0)
{
delete this;
return true;
}
return false;
}
//ReferenceManager.h
#include <string>
#include <Windows.h>
using namespace std;
class CReferenceCount
{
public:
CReferenceCount();
virtual ~CReferenceCount();
virtual void AddRef();
virtual bool Release();
private:
LONG m_ref;
};
//test.cpp
#include "stdafx.h"
#include "ReferenceCount.h"
#include "RefManager.h"
#include <iostream>
using namespace std;
class Test1: public CReferenceCount
{
public:
Test1(){}
~Test1(){}
private :
int m_i;
};
void main()
{
Test1 *pTest= new Test1();
CReferenceManager<Test1> testRef(pTest);
}
Similare questions I have posted
finding who creates object via smart pointer
Design pattern to detect memory leaks for reference counted smart pointers
but non of the answers give right explanation to tackle this proble,
The only way is to define macros for calling AddRef and Release, since there is no way for the functions to know internally from where they are being called. So you could use something like.
#define RELEASE(obj) cout << __LINE__ << ":" << __FILE__ << endl; (obj).Release();
Also, different compilers have different pre-defined macros; if portability is a concern, it's something you should look into when writing code like the above. MSDN reference (2003)
Given your comments below, i might offer another somewhat hackish solution. You may not be able to see where your reference is being released, but you can get more information about where it was created, and which are not being released properly.
template <typename T>
struct CReferenceManager
{
CReferenceManager(const T & _obj, const string & _file, int _line) : mObj(_obj), mFile(_file), mLine(_line)
{
cout << "Constructing from " << _file << ":" << _line << endl;
CReferenceManager::sObjects[make_pair(mFile, mLine)]++;
mObj.addRef();
}
~CReferenceManager()
{
cout << "Destructing object created at " << mFile << ":" << mLine << endl;
CReferenceManager::sObjects[make_pair(mFile, mLine)]--;
mObj.Release();
}
static map<pair<string, int>, int> sObjects;
string mFile;
int mLine;
T obj;
}
int main()
{
...
// Cycle through sObjects before return, note any unreleased entries
return 0;
}
Note this is just pseudo-code; I doubt it compiles or works out of the box!
You should never allocate or release references explicitly in your own code, so storing the source file and line where references are incremented or decremented isn't going to help you at all, since those will (should!) always be inside the reference counting management code.
You did not include the source code to your CReferenceManager class, but based on your description it is a wrapper to a referenced counted object. Is this correct? The correct implementation of this CReferenceManager object should ensure that:
a constructor that takes a naked pointer stores the pointer and does not change the reference count (since your CReferenceCount class creates object with one reference)
reference is always decremented in the destructor
reference is incremented in the copy-constructor
reference for the right side object is incremented, and reference for the left side object is decremented in the assignment operator
no explicit increment/decrement reference methods should be exposed
the operator->() method should return the pointer to the object
there should be no direct way to detach the reference counted object from a CReferenceManager instance that owns it. The only way is via assignment of a new reference counted object.
Also, you'd want to make the AddRef() and Release() methods in your CReferenceCount class private, and make them accessible only to the CReferenceManager class via class friendship.
If you follow the above rules in your CReferenceManager class, then you can avoid leaks or other memory problems by ensuring that everybody accesses the object via a CReferenceManager wrapper allocated on the stack. In other words:
To create a new referenced counted object, passed a newly created object (with one reference) to a stack allocated CReferenceManager object. Example:
CReferenceManager<Test1> testRef(new Test1());
To pass the object as an argument to another function or method, always pass a CReferenceManager object by value (not by reference, and not by pointer). If you do it this way the copy constructor and the destructor will take care of maintaining the reference counts for you. Example:
void someFunction(CReferenceManager<Test1> testObj)
{
// use testObj as if it was a naked pointer
// reference mananagement is automatically handled
printf("some value: %d\n", testObj->someValue());
}
int main()
{
CReferenceManager<Test1> testRef(new Test1());
someFunction(testRef);
}
If you need to stick the reference counted object in a container, then insert a CReferenceManager wrapper by value (not its pointer, and not the object's naked pointer). Example:
std::vector< CReferenceManager<Test1> > myVector;
CReferenceManager<Test1> testRef(new Test1());
myVector.push_back(testRef);
myVector[0]->some_method(); // invoke the object as if it was a pointer!
I believe if you strictly follow the above rules the only problems you will find are bugs in your reference counting implementation.
An example implementation that follows these rules is in this page, though that solution lacks any support for multi-threading protection.
I hope this helps!
There is some way of doing this, but first let me ask you one thing. Why you want to manage references by hand and provide an opportunity for memory leaks? you can easily use boost::intrusive_ptr to do the job for you?( if you don't want the boost, there is no problem, see implementation of intrusive_ptr and implement your own class or just copy it to your own file ) and then you don't have a memory leak to search for it!!
But as an answer for your question you could have 2 AddRef/Release one for debug version and another for release and you should add AddRef positions to an structure like std::stack and on Release pop them from stack and at very end you see how much references from witch positions remained in the stack! but if this is for COM implementation remember that COM may call AddRef multiple time and then remove them at later time and thus you can't understand which AddRef have no corresponding Release.
For the projects I am involved in I had similar needs. We have our own smart-pointer template class and from time to time memory leaks appeared due to circular references.
To know which smart-pointer referencing a leaked object still is alive (2 or more), we compile the sources with a special pre-processor define which enables special debugging code in the smart-pointer implementation. You can have a look at our smart-pointer class.
In essence, each smart-pointer and reference counted object get a unique id. When we get the id for the leaked object (usually using valgrind to identify the source location of the memory allocation for the leaked object), we use our special debugging code to get all smart-pointer ids which reference the object. Then we use a configuration file where we write down the smart-pointer ids and at next application start-up, this file is read by our debugging tool which then knows for which newly created smart-pointer instance it should trigger a signal for entering the debugger. This reveals the stack trace where that smart-pointer instance was created.
Admittedly, this involves some work and might only pay off for larger projects.
Another possibility would be to record a stack trace inside your AddRef method at runtime. Have a look at my ctkBackTrace class to create a stack trace at runtime. It should be easy to replace the Qt specific types by standard STL types.
I guess that with a bit of work and using libunwind you could probably try to get what you need (which would be a really appreciated).
http://www.nongnu.org/libunwind/docs.html
The principle of reference counting is to increase the counter when the user link to the object and to decrease when they break the link.
So you have to:
manipulate smart pointers, not pointers to make increase/decrease transparent
overload copy constructor and assign operator of the smart_pointer
Symbolic exemple:
A a = new A(); refcount = 0, nobody use it
Link<A> lnk( a ); refcount = 1
obj.f( lnk ); obj stores lnk, refcount = 2
this method may returns since the ownership has been transfered to obj
So, take a look at parameter passing (may do automatic copies) and at copy into foreign objects.
Good tutorials exists on that in the CORBA nebulae.
You may see also ACE or ICE, or 0MQ.
One way to do what you asked, is to pass AddRef and Release this information using something like this:
void CReferenceCount::AddRef(const char *file=0, int line=-1) { if (file) cout << "FILE:" << file; if (line>0) count << " LINE: " << line; .... do the rest here ... }
Then when you call the function, you can use a macro similar to what Rollie suggested above, like this:
#define ADDREF(x) x.AddRef(__FILE__, __LINE__)
This will pass the file and line where the call is made, which I believe is what you asked for. You can control what you want to do with the information within the methods. Printing them out, as I did above, is just an example. You may want to collect more information beyond this, and log it to another object, so you have a history of your calls, write them to a log file, etc. You may also pass more information from the call points than just the file and line, according to the type and level of tracking you need. The default parameters also allow you to use them without passing anything (by a simple macro redefinition), just to see how the final version will behave, with the overhead of two stack pushes and two condition checks.
Short answer: you should use the ideas that others posted, namely making use of ADD/RELEASE macros and passing the predefined __FILE__ and __LINE__ macros that the compiler provides to your tracking class.
Slightly longer answer: You can also use functionality that allows you to walk the stack and see who called the function, which is somewhat more flexible and clean than using macros, but almost certainly slower.
This page shows you how to achieve this when using GCC: http://tombarta.wordpress.com/2008/08/01/c-stack-traces-with-gcc/.
In Windows you can use some compiler intrinsics along with symbol-lookup functionality. For details check out: http://www.codeproject.com/tools/minidump.asp
Note that in both cases your program would need to include at least some symbols for this to work.
Unless you have special requirements for doing this at runtime, I'd suggest you check out the short answer.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What are the differences between pointer variable and reference variable in C++?
What does Class& mean in c++ and how is it different from Class*?
Class& foo;
Class* foo;
The & version represents a reference while the * version represents a pointer. The difference is far too big for a typical SO post. I suggest you start at the C++ FAQ lite
http://www.parashift.com/c++-faq-lite/references.html
I usually don't like to answer posts with a "you should use google" answer. However this is one topic that I highly advise you google. In particular google "c++ pointers vs. references". There is a wealth of information available on this topic and the discussions on those pages will trump anything we'll write here.
The * is a pointer, the & is a reference. The difference between the two is that a pointer is an area of memory that must be dereferenced, eg. by means of the -> operator in order to be "seen" as a class instance. A reference is instead an "alias", just an alternative name for the same class instance. You don't need to use the -> operator with a reference. You use the dot operator.
Personally, I rarely used the references, mostly when I had a value object that I allocated on the stack. The new operator always returns a pointer, which you then have to dereference. Moreover, one of the most problematic issues of the references is that you cannot set them to NULL. In some cases, it is handy to have a function that accepts either an object pointer or NULL. If your function accepts a reference, you cannot pass a NULL (you could use the Null object pattern, however)
A Class * can point at any class object, or none.
A Class & always points to exactly one class object, and can never point to a different one.
Furthermore, I believe Bjarne is a member of the set of people who have asserted "arrays in C are broken beyond repair," a Class * can point at a whole ding-dang array of class objects, lined up one after the other in memory, and there is absolutely no way in C to tell whether a Class * points at one or many.
Another difference is that reference variables must be initialized. You cannot create a reference variable like what is shown in the sample code. That would produce a compiler error.
As stated you should google it, but to avoid misunderstanding:
References are NOT variables
References are NOT similar to pointers (but you can use them in a similar way)
Think of a Reference as a shortcut for the term that is assigned to it.
One additional tip that I would offer is the following:
Use references when you can, pointers when you have to. If the object is guaranteed to exist, you should probably use a reference. If it is not, then you probably have to use a pointer.
One additional advantage is that references remove ambiguity on ownership. As soon as a maintenance programmer sees a pointer, they'll start to wonder if they should delete it.
Check this example out:
// Wrapper class using a reference because the wrapped object always exists
class Wrapper
{
public:
// If the wrapped is guaranteed to exist at creation, do it this way
Wrapper(Wrapped& wrapped):_wrapped(wrapped) { /* empty */ }
// put extra methods here.
int getWrappedValue() const { return _wrapped.getValue(); }
private:
Wrapped& _wrapped; // This object always exists and is valid
};
// Wrapper class written to support a possibly non-existent wrapped object.
class Wrapper
{
public:
Wrapper(Wrapped* wrapped = 0):_wrapped(wrapped) { /* empty */
void setWrappee(WRappee* wrapped) { _wrapped = wrapped; }
int getWrappedValue() const; // Not making inline -- more complex
private:
Wrapped* _wrapped; // Always check pointer before use
};
int Wrapper::getWrappedValue() const
{
if (_wrapped)
{
return _wrapped->getValue();
}
else
{
return -1; // NOTE, this is a contrived example -- not getting into exceptions
}
}
A reference (&) is just the same as a pointer (*), except that the C++ compiler ensures it not to be NULL. However, it can still be a dangling pointer (a pointer variable that has no reference such that it is garbage and invalid for any use).
What are some ways you can shoot yourself in the foot when using boost::shared_ptr? In other words, what pitfalls do I have to avoid when I use boost::shared_ptr?
Cyclic references: a shared_ptr<> to something that has a shared_ptr<> to the original object. You can use weak_ptr<> to break this cycle, of course.
I add the following as an example of what I am talking about in the comments.
class node : public enable_shared_from_this<node> {
public :
void set_parent(shared_ptr<node> parent) { parent_ = parent; }
void add_child(shared_ptr<node> child) {
children_.push_back(child);
child->set_parent(shared_from_this());
}
void frob() {
do_frob();
if (parent_) parent_->frob();
}
private :
void do_frob();
shared_ptr<node> parent_;
vector< shared_ptr<node> > children_;
};
In this example, you have a tree of nodes, each of which holds a pointer to its parent. The frob() member function, for whatever reason, ripples upwards through the tree. (This is not entirely outlandish; some GUI frameworks work this way).
The problem is that, if you lose reference to the topmost node, then the topmost node still holds strong references to its children, and all its children also hold a strong reference to their parents. This means that there are circular references keeping all the instances from cleaning themselves up, while there is no way of actually reaching the tree from the code, this memory leaks.
class node : public enable_shared_from_this<node> {
public :
void set_parent(shared_ptr<node> parent) { parent_ = parent; }
void add_child(shared_ptr<node> child) {
children_.push_back(child);
child->set_parent(shared_from_this());
}
void frob() {
do_frob();
shared_ptr<node> parent = parent_.lock(); // Note: parent_.lock()
if (parent) parent->frob();
}
private :
void do_frob();
weak_ptr<node> parent_; // Note: now a weak_ptr<>
vector< shared_ptr<node> > children_;
};
Here, the parent node has been replaced by a weak pointer. It no longer has a say in the lifetime of the node to which it refers. Thus, if the topmost node goes out of scope as in the previous example, then while it holds strong references to its children, its children don't hold strong references to their parents. Thus there are no strong references to the object, and it cleans itself up. In turn, this causes the children to lose their one strong reference, which causes them to clean up, and so on. In short, this wont leak. And just by strategically replacing a shared_ptr<> with a weak_ptr<>.
Note: The above applies equally to std::shared_ptr<> and std::weak_ptr<> as it does to boost::shared_ptr<> and boost::weak_ptr<>.
Creating multiple unrelated shared_ptr's to the same object:
#include <stdio.h>
#include "boost/shared_ptr.hpp"
class foo
{
public:
foo() { printf( "foo()\n"); }
~foo() { printf( "~foo()\n"); }
};
typedef boost::shared_ptr<foo> pFoo_t;
void doSomething( pFoo_t p)
{
printf( "doing something...\n");
}
void doSomethingElse( pFoo_t p)
{
printf( "doing something else...\n");
}
int main() {
foo* pFoo = new foo;
doSomething( pFoo_t( pFoo));
doSomethingElse( pFoo_t( pFoo));
return 0;
}
Constructing an anonymous temporary shared pointer, for instance inside the arguments to a function call:
f(shared_ptr<Foo>(new Foo()), g());
This is because it is permissible for the new Foo() to be executed, then g() called, and g() to throw an exception, without the shared_ptr ever being set up, so the shared_ptr does not have a chance to clean up the Foo object.
Be careful making two pointers to the same object.
boost::shared_ptr<Base> b( new Derived() );
{
boost::shared_ptr<Derived> d( b.get() );
} // d goes out of scope here, deletes pointer
b->doSomething(); // crashes
instead use this
boost::shared_ptr<Base> b( new Derived() );
{
boost::shared_ptr<Derived> d =
boost::dynamic_pointer_cast<Derived,Base>( b );
} // d goes out of scope here, refcount--
b->doSomething(); // no crash
Also, any classes holding shared_ptrs should define copy constructors and assignment operators.
Don't try to use shared_from_this() in the constructor--it won't work. Instead create a static method to create the class and have it return a shared_ptr.
I've passed references to shared_ptrs without trouble. Just make sure it's copied before it's saved (i.e., no references as class members).
Here are two things to avoid:
Calling the get() function to get the raw pointer and use it after the pointed-to object goes out of scope.
Passing a reference of or a raw pointer to a shared_ptr should be dangerous too, since it won't increment the internal count which helps keep the object alive.
We debug several weeks strange behavior.
The reason was:
we passed 'this' to some thread workers instead of 'shared_from_this'.
Not precisely a footgun, but certainly a source of frustration until you wrap your head around how to do it the C++0x way: most of the predicates you know and love from <functional> don't play nicely with shared_ptr. Happily, std::tr1::mem_fn works with objects, pointers and shared_ptrs, replacing std::mem_fun, but if you want to use std::negate, std::not1, std::plus or any of those old friends with shared_ptr, be prepared to get cozy with std::tr1::bind and probably argument placeholders as well. In practice this is actually a lot more generic, since now you basically end up using bind for every function object adaptor, but it does take some getting used to if you're already familiar with the STL's convenience functions.
This DDJ article touches on the subject, with lots of example code. I also blogged about it a few years ago when I first had to figure out how to do it.
Using shared_ptr for really small objects (like char short) could be an overhead if you have a lot of small objects on heap but they are not really "shared". boost::shared_ptr allocates 16 bytes for every new reference count it creates on g++ 4.4.3 and VS2008 with Boost 1.42. std::tr1::shared_ptr allocates 20 bytes. Now if you have a million distinct shared_ptr<char> that means 20 million bytes of your memory are gone in holding just count=1. Not to mention the indirection costs and memory fragmentation. Try with the following on your favorite platform.
void * operator new (size_t size) {
std::cout << "size = " << size << std::endl;
void *ptr = malloc(size);
if(!ptr) throw std::bad_alloc();
return ptr;
}
void operator delete (void *p) {
free(p);
}
Giving out a shared_ptr< T > to this inside a class definition is also dangerous.
Use enabled_shared_from_this instead.
See the following post here
You need to be careful when you use shared_ptr in multithread code. It's then relatively easy to become into a case when couple of shared_ptrs, pointing to the same memory, is used by different threads.
The popular widespread use of shared_ptr will almost inevitably cause unwanted and unseen memory occupation.
Cyclic references are a well known cause and some of them can be indirect and difficult to spot especially in complex code that is worked on by more than one programmer; a programmer may decide than one object needs a reference to another as a quick fix and doesn't have time to examine all the code to see if he is closing a cycle. This hazard is hugely underestimated.
Less well understood is the problem of unreleased references. If an object is shared out to many shared_ptrs then it will not be destroyed until every one of them is zeroed or goes out of scope. It is very easy to overlook one of these references and end up with objects lurking unseen in memory that you thought you had finished with.
Although strictly speaking these are not memory leaks (it will all be released before the program exits) they are just as harmful and harder to detect.
These problems are the consequences of expedient false declarations: 1. Declaring what you really want to be single ownership as shared_ptr. scoped_ptr would be correct but then any other reference to that object will have to be a raw pointer, which could be left dangling. 2. Declaring what you really want to be a passive observing reference as shared_ptr. weak_ptr would be correct but then you have the hassle of converting it to share_ptr every time you want to use it.
I suspect that your project is a fine example of the kind of trouble that this practice can get you into.
If you have a memory intensive application you really need single ownership so that your design can explicitly control object lifetimes.
With single ownership opObject=NULL; will definitely delete the object and it will do it now.
With shared ownership spObject=NULL; ........who knows?......
If you have a registry of the shared objects (a list of all active instances, for example), the objects will never be freed. Solution: as in the case of circular dependency structures (see Kaz Dragon's answer), use weak_ptr as appropriate.
Smart pointers are not for everything, and raw pointers cannot be eliminated
Probably the worst danger is that since shared_ptr is a useful tool, people will start to put it every where. Since plain pointers can be misused, the same people will hunt raw pointers and try to replace them with strings, containers or smart pointers even when it makes no sense. Legitimate uses of raw pointers will become suspect. There will be a pointer police.
This is not only probably the worst danger, it may be the only serious danger. All the worst abuses of shared_ptr will be the direct consequence of the idea that smart pointers are superior to raw pointer (whatever that means), and that putting smart pointers everywhere will make C++ programming "safer".
Of course the mere fact that a smart pointer needs to be converted to a raw pointer to be used refutes this claim of the smart pointer cult, but the fact that the raw pointer access is "implicit" in operator*, operator-> (or explicit in get()), but not implicit in an implicit conversion, is enough to give the impression that this is not really a conversion, and that the raw pointer produced by this non-conversion is an harmless temporary.
C++ cannot be made a "safe language", and no useful subset of C++ is "safe"
Of course the pursuit of a safe subset ("safe" in the strict sense of "memory safe", as LISP, Haskell, Java...) of C++ is doomed to be endless and unsatisfying, as the safe subset of C++ is tiny and almost useless, as unsafe primitives are the rule rather than the exception. Strict memory safety in C++ would mean no pointers and only references with automatic storage class. But in a language where the programmer is trusted by definition, some people will insist on using some (in principle) idiot-proof "smart pointer", even where there is no other advantage over raw pointers that one specific way to screw the program state is avoided.