Store temporary pointer before releasing to avoid referencing - c++

I'm new to C++ and have been stumped on this code in RefCountObject.h from Angle project
void set(const ContextType *context, ObjectType *newObject)
{
// addRef first in case newObject == mObject and this is the last reference to it.
if (newObject != nullptr)
{
reinterpret_cast<RefCountObject<ContextType, ErrorType> *>(newObject)->addRef();
}
// Store the old pointer in a temporary so we can set the pointer before calling release.
// Otherwise the object could still be referenced when its destructor is called.
ObjectType *oldObject = mObject;
mObject = newObject;
if (oldObject != nullptr)
{
reinterpret_cast<RefCountObject<ContextType, ErrorType> *>(oldObject)->release(context);
}
}
I don't understand the second comment, what the temporary pointer helps to avoid referencing an object when its destructor is called? Is it a best practice?

I think the purpose of this is to ensure that mObjects is always valid (i.e. it always point to a valid/existing object).
A rationale behind that would be in the case if something in the program is likely to consume/read the value pointed by mObject at anytime (a thread or whatever), we must guarantee that it will never happen when the variable is deleted and before it is reassigned.
This would explain the need to keep the variable always valid and to release it after having already reassigned it (thus requiring to get a temporary to delay the deletion of the old/replaced object).

Related

Return by reference in C++ - Reference assignment vs value assignment

Suppose I have:
class SomeObject {
};
SomeObject& f() {
SomeObject *s = new SomeObject();
return *s;
}
// Variant 1
int main() {
SomeObject& s = f();
// Do something with s
}
// Variant 2
int main() {
SomeObject s = f();
// Do something with s
}
Is there any difference between the first variant and the second? any cases I would use one over the other?
Edit: One more question, what does s contain in both cases?
First, you never want to return a reference to an object which
was dynamically allocated in the function. This is a memory
leak waiting to happen.
Beyond that, it depends on the semantics of the object, and what
you are doing. Using the reference (variant 1) allows
modification of the object it refers to, so that some other
function will see the modified value. Declaring a value
(variant 2) means that you have your own local copy, and any
modifications, etc. will be to it, and not to the object
referred to in the function return.
Typically, if a function returns a reference to a non-const,
it's because it expects the value to be modified; a typical
example would be something like std::vector<>::operator[],
where an expression like:
v[i] = 42;
is expected to modify the element in the vector. If this is
not the case, then the function should return a value, not
a reference (and you should almost never use such a function to
initialize a local reference). And of course, this only makes
sense if you return a reference to something that is accessible
elsewhere; either a global variable or (far more likely) data
owned by the class of which the function is a member.
In the first variant you attach a reference directly to a dynamically allocated object. This is a rather unorthodox way to own dynamic memory (a pointer would be better suited for that purpose), but still it gives you the opportunity to properly deallocate that object. I.e. at the end of your first main you can do
delete &s;
In the second variant you lose the reference, i.e. you lose the only link to that dynamically allocated object. The object becomes a memory leak.
Again, owning a dynamically allocated object through a reference does not strike me as a good practice. It is usually better to use a pointer or a smart pointer for that purpose. For that reason, both of your variants are flawed, even though the first one is formally redeemable.
Variant 1 will copy the address of the object and will be fast
Variant 2 will copy the whole object and will be slow (as already pointed out in Variant2 you cant delete the object which you created by calling new)
for the edit: Both f contain the same Object
None of the two options you asked about is very good. In this particular case you should use shared_ptr or unique_ptr, or auto_ptr if you use older C++ compilers, and change the function so it returns pointer, not reference. Another good option is returning the object by value, especially if the object is small and cheap to construct.
Modification to return the object by value:
SomeObject f() { return SomeObject(); }
SomeObject s(f());
Simple, clean, safe - no memory leaking here.
Using unique_ptr:
SomeObject* f() { return new SomeObject(); }
unique_ptr<SomeObject> s(f());
One of the advantages of using a unique_ptr or shared_ptr here is that you can change your function f at some point to return objects of a class derived from SomeObject and none of your client code will need to be changed - just make sure the base class (SomeObject) has a virtual constructor.
Why the options you were considering are not very good:
Variant 1:
SomeObject& s = f();
How are you going to destroy the object? You will need address of the object to call it's destructor anyway, so at some point you would need to dereference the object that s refers to (&s)
Variant 2. You have a leak here and not a chance to call destructor of the object returned from your function.

Does destroying and recreating an object make all pointers to this object invalid?

This is a follow-up to this question. Suppose I have this code:
class Class {
public virtual method()
{
this->~Class();
new( this ) Class();
}
};
Class* object = new Class();
object->method();
delete object;
which is a simplified version of what this answer suggests.
Now once a destructor is invoked from within method() the object lifetime ends and the pointer variable object in the calling code becomes invalid. Then the new object gets created at the same location.
Does this make the pointer to the object in the calling valid again?
This is explicitly approved in 3.8:7:
3.8 Object lifetime [basic.life]
7 - If, after the lifetime of an object has ended [...], a new object is created at the storage location which the original object occupied, a pointer that pointed to the original object [...] can be used to manipulate the new object, if: (various requirements which are satisfied in this case)
The example given is:
struct C {
int i;
void f();
const C& operator=( const C& );
};
const C& C::operator=( const C& other) {
if ( this != &other ) {
this->~C(); // lifetime of *this ends
new (this) C(other); // new object of type C created
f(); // well-defined
}
return *this;
}
Strictly, this is fine. However, without extreme care, it will become a hideous piece of UB. For example, any derived classes calling this method won't get the right type re-constructed- or what happens if Class() throws an exception. Furthermore, this doesn't really accomplish anything.
It's not strictly UB, but is a giant pile of crap and fail and should be burned on sight.
The object pointer doesn't become invalid at any time (assuming your destructor doesn't call delete this). Your object was never deallocated, it has only called it's destructor, i.e. it has cleaned up its internal state (with regard to implementation, please note that standard strictly defines that the object is destroyed after destructor call). As you have used placement new to instantiate the new object at the exactly same address, it is technically ok.
This exact scenario is covered by section 3.8.7 of C++ standard:
If, after the lifetime of an object has ended and before the storage
which the object occupied is reused or released, a new object is
created at the storage location which the original object occupied, a
pointer that pointed to the original object, a reference that referred
to the original object, or the name of the original object will
automatically refer to the new object and, once the lifetime of the
new object has started, can be used to manipulate the new object [...]
That said, this is interesting only as learning code, as production code, this is horrible :)
The pointer only knows its address and as soon as you can confirm that the address of the new object is the one the pointer is pointing to, the answer is yes.
There are some cases where people would believe the address does not change, but in some cases it does change, e.g. when using C's realloc(). But that's another story.
You may want to reconsider explicitly calling the destructor. If there's code you want executed that happens to be in the destructor, move that code to a new method and call that method from the destructor to preserve the current functionality. The destructor is really meant to be used for objects going out of scope.
Creating a new object at the location of a destroyed one does not make any pointers valid again. They may point to a valid new object, but not the object you were originally referencing.
You should guarantee that all references were removed or somehow marked as invalid before destroying the original object.
This would be a particularly difficult situation to debug.

Explicitly deleting a shared_ptr

Simple question here: are you allowed to explicitly delete a boost::shared_ptr yourself? Should you ever?
Clarifying, I don't mean delete the pointer held by the shared_ptr. I meant the actual shared_ptr itself. I know most people suggest to not do it, so I was just wondering if it's OK to explicitly do it.
Your question isn't clear. If you've allocated a shared_ptr dynamically then you're certainly allowed to delete it whenever you want.
But if you're asking whether you're allowed to delete whatever object is being managed by the shared_ptr, then the answer is ... it depends. If shared_ptr::unique returns true, then calling shared_ptr::reset will delete the managed object. However, if shared_ptr::unique returns false, it means there are more than one shared_ptrs sharing ownership of that object. In this case a call to reset will only result in the reference count being decremented by 1, actual deletion of the object will take place when the last shared_ptr managing that object either goes out of scope or is itself reset.
EDIT:
After your edit, it seems you are asking about deleting a dynamically allocated shared_ptr. Something like this:
auto sp = new boost::shared_ptr<int>( new int(42) );
// do something with sp
delete sp;
This is allowed and will work as expected, although it would be an unusual use case. The only caveat is that if in between the allocation and deletion of sp you create another shared_ptr that shares ownership of the object, deleting sp will not result in deletion of the object, that will only happen when the reference count for the object goes to 0.
[Edit: you can delete a shared_ptr if and only if it was created with new, same as any other type. I can't think why you'd create a shared_ptr with new, but there's nothing stopping you.]
Well, you could write delete ptr.get();.
Doing so leads almost inevitably to undefined behavior either when the other shared owners use their shared_ptr to access the now-deleted object, or the last shared_ptr to the object is destroyed, and the object gets deleted again.
So no, you shouldn't.
The purpose of shared_ptr is to manage an object that no one "person" has the right or responsibility to delete, because there could be others sharing ownership. So you shouldn't ever want to, either.
If you want to simulate the count decrement, you can do it manually on the heap like so:
int main(void) {
std::shared_ptr<std::string>* sp = new std::shared_ptr<std::string>(std::make_shared<std::string>(std::string("test")));
std::shared_ptr<std::string>* sp2 = new std::shared_ptr<std::string>(*sp);
delete sp;
std::cout << *(*sp2) << std::endl; // test
return 0;
}
Or on the stack using std::shared_ptr::reset() like so:
int main(void) {
std::shared_ptr<std::string> p = std::make_shared<std::string>(std::string("test"));
std::shared_ptr<std::string> p2 = p;
p.reset();
std::cout << *p2 << std::endl; // test
return 0;
}
But it's not that useful.
You cannot force its reference count to zero, no.
Think about what would be required for that to work. You would need to go to each place the shared_ptr is used and clear it.
If you did force the shared pointer to delete and set it to NULL, it would be just like a weak_ptr. However, all those places in the code using that shared_ptr are not ready for that and expect to be holding a valid pointer. They have no reason to check for NULL, and so those bits of code would crash.
Expliticly deleting comes in handy in some (very?) rare cases.
In addition to explicitly deleting, sometimes you HAVE to explicitly destruct a shared pointer when you are 'deleting' it!
Things can get weird when interfacing with C code, passing a shared_ptr as an opaque value.
For example I have the following for passing objects to and from the Lua scripting language which is written in C. (www.lua.org)
static void push( lua_State *L, std::shared_ptr<T> sp )
{
if( sp == nullptr ) {
lua_pushnil( L );
return;
}
// This is basically malloc from C++ point of view.
void *ud = lua_newuserdata( L, sizeof(std::shared_ptr<T>));
// Copy constructor, bumps ref count.
new(ud) std::shared_ptr<T>( sp );
luaL_setmetatable( L, B::class_name );
}
So thats a shared_ptr in some malloc'd memory. The reverse is this... (setup to be called just before Lua garbage collects an object and 'free's it).
static int destroy( lua_State *L )
{
// Grab opaque pointer
void* ud = luaL_checkudata( L, 1, B::class_name );
std::shared_ptr<T> *sp = static_cast<std::shared_ptr<T>*>(ud);
// Explicitly called, as this was 'placement new'd
// Decrements the ref count
sp->~shared_ptr();
return 0;
}

Check for non-deallocated pointer

Assume a pointer object is being allocated on one point and it is being returned to different nested functions. At one point, I want to de-allocate this pointer after checking whether it is valid or already de-allocated by someone.
Is there any guarantee that any of these will work?
if(ptr != NULL)
delete ptr;
OR
if(ptr)
delete ptr;
This code does not work. It always gives Segmentation Fault
#include <iostream>
class A
{
public:
int x;
A(int a){ x=a;}
~A()
{
if(this || this != NULL)
delete this;
}
};
int main()
{
A *a = new A(3);
delete a;
a=NULL;
}
EDIT
Whenever we talk about pointers, people start asking, why not use Smart Pointers.
Just because smart pointers are there, everyone cannot use it.
We may be working on systems which use old style pointers. We cannot convert all of them to smart pointers, one fine day.
if(ptr != NULL) delete ptr;
OR
if(ptr) delete ptr;
The two are actually equivalent, and also the same as delete ptr;, because calling delete on a NULL pointer is guaranteed to work (as in, it does nothing).
And they are not guaranteed to work if ptr is a dangling pointer.
Meaning:
int* x = new int;
int* ptr = x;
//ptr and x point to the same location
delete x;
//x is deleted, but ptr still points to the same location
x = NULL;
//even if x is set to NULL, ptr is not changed
if (ptr) //this is true
delete ptr; //this invokes undefined behavior
In your specific code, you get the exception because you call delete this in the destructor, which in turn calls the destructor again. Since this is never NULL, you'll get a STACK OVERFLOW because the destructor will go uncontrollably recursive.
Do not call delete this in the destructor:
5.3.5, Delete: If the value of the operand of the delete-expression is not a null pointer value, the delete-expression will
invoke the destructor (if any) for the object or the elements of the array being deleted.
Therefore, you will have infinite recursion inside the destructor.
Then:
if (p)
delete p;
the check for p being not null (if (x) in C++ means if x != 0) is superfluous. delete does that check already.
This would be valid:
class Foo {
public:
Foo () : p(0) {}
~Foo() { delete p; }
private:
int *p;
// Handcrafting copy assignment for classes that store
// pointers is seriously non-trivial, so forbid copying:
Foo (Foo const&) = delete;
Foo& operator= (Foo const &) = delete;
};
Do not assume any builtin type, like int, float or pointer to something, to be initialized automatically, therefore, do not assume them to be 0 when not explicitly initializing them (only global variables will be zero-initialized):
8.5 Initializers: If no initializer is specified for an object, the object is default-initialized; if no initialization is performed, an
object with automatic or dynamic storage duration has indeterminate value. [ Note: Objects with static or thread storage duration are zero-initialized
So: Always initialize builtin types!
My question is how should I avoid double delete of a pointer and prevent crash.
Destructors are ought to be entered and left exactly once. Not zero times, not two times, once.
And if you have multiple places that can reach the pointer, but are unsure about when you are allowed to delete, i.e. if you find yourself bookkeeping, use a more trivial algorithm, more trivial rules, or smart-pointers, like std::shared_ptr or std::unique_ptr:
class Foo {
public:
Foo (std::shared_ptr<int> tehInt) : tehInt_(tehInt) {}
private:
std::shared_ptr<int> tehInt_;
};
int main() {
std::shared_ptr<int> tehInt;
Foo foo (tehInt);
}
You cannot assume that the pointer will be set to NULL after someone has deleted it. This is certainly the case with embarcadero C++ Builder XE. It may get set to NULL afterwards but do not use the fact that it is not to allow your code to delete it again.
You ask: "At one point, I want to de-allocate this pointer after checking whether it is valid or already de-allocated by someone."
There is no portable way in C/C++ to check if a >naked pointer< is valid or not. That's it. End of story right there. You can't do it. Again: only if you use a naked, or C-style pointer. There are other kinds of pointers that don't have that issue, so why don't use them instead!
Now the question becomes: why the heck do you insist that you should use naked pointers? Don't use naked pointers, use std::shared_ptr and std::weak_ptr appropriately, and you won't even need to worry about deleting anything. It'll get deleted automatically when the last pointer goes out of scope. Below is an example.
The example code shows that there are two object instances allocated on the heap: an integer, and a Holder. As test() returns, the returned std::auto_ptr<Holder> is not used by the caller main(). Thus the pointer gets destructed, thus deleting the instance of the Holder class. As the instance is destructed, it destructs the pointer to the instance of the integer -- the second of the two pointers that point at that integer. Then myInt gets destructed as well, and thus the last pointer alive to the integer is destroyed, and the memory is freed. Automagically and without worries.
class Holder {
std::auto_ptr<int> data;
public:
Holder(const std::auto_ptr<int> & d) : data(d) {}
}
std::auto_ptr<Holder> test() {
std::auto_ptr<int> myInt = new int;
std::auto_ptr<Holder> myHolder = new Holder(myInt);
return myHolder;
}
int main(int, char**) {
test(); // notice we don't do any deallocations!
}
Simply don't use naked pointers in C++, there's no good reason for it. It only lets you shoot yourself in the foot. Multiple times. With abandon ;)
The rough guidelines for smart pointers go as follows:
std::auto_ptr -- use when the scope is the sole owner of an object, and the lifetime of the object ends when the scope dies. Thus, if auto_ptr is a class member, it must make sense that the pointed-to object gets deletes when the instance of the class gets destroyed. Same goes for using it as an automatic variable in a function. In all other cases, don't use it.
std::shared_ptr -- its use implies ownership, potentially shared among multiple pointers. The pointed-to object's lifetime ends when the last pointer to it gets destroyed. Makes managing lifetime of objects quite trivial, but beware of circular references. If Class1 owns an instance of Class2, and that very same instance of Class2 owns the former instance of Class1, then the pointers themselves won't ever delete the classes.
std::weak_ptr -- its use implies non-ownership. It cannot be used directly, but has to be converted back to a shared_ptr before use. A weak_ptr will not prevent an object from being destroyed, so it doesn't present circular reference issues. It is otherwise safe in that you can't use it if it's dangling. It will assert or present you with a null pointer, causing an immediate segfault. Using dangling pointers is way worse, because they often appear to work.
That's in fact the main benefit of weak_ptr: with a naked C-style pointer, you'll never know if someone has deleted the object or not. A weak_ptr knows when the last shared_ptr went out of scope, and it will prevent you from using the object. You can even ask it whether it's still valid: the expired() method returns true if the object was deleted.
You should never use delete this. For two reasons, the destructor is in the process of deleting the memory and is giving you the opportunity to tidy up (release OS resources, do a delete any pointers in the object that the object has created). Secondly, the object may be on the stack.

Do I need to nullify a member variable in the destructor?

Why one would want to explicitly clear the a vector member variable (of on in a dtor (please see the code below). what are the benefits of clearing the vector, even though it will be destroyed just after the last line of dtor code will get executed?
class A
{
~A()
{
values.clear();
}
private:
std::vector < double > values_;
};
similar question about a the following code:
class B
{
~B()
{
if (NULL != p)
{
delete p_;
p_ = NULL;
}
}
private:
A * p_;
};
Since there is no way the dtor will get called twice, why to nullify p_ then?
In class A, there is absolutely no reason to .clear() the vector-type member variable in the destructor. The vector destructor will .clear() the vector when it is called.
In class B, the cleanup code can simply be written as:
delete p_;
There is no need to test whether p_ != NULL first because delete NULL; is defined to be a no-op. There is also no need to set p_ = NULL after you've deleted it because p_ can no longer be legitimately accessed after the object of which it is a member is destroyed.
That said, you should rarely need to use delete in C++ code. You should prefer to use Scope-Bound Resource Management (SBRM, also called Resource Acquisition Is Initialization) to manage resource lifetimes automatically.
In this case, you could use a smart pointer. boost::scoped_ptr and std::unique_ptr (from C++0x) are both good choices. Neither of them should have any overhead compared to using a raw pointer. In addition, they both suppress generation of the implicitly declared copy constructor and copy assignment operator, which is usually what you want when you have a member variable that is a pointer to a dynamically allocated object.
In your second example there's no reason to set p_ to null whatsoever, specifically because it is done in the destructor, meaning that the lifetime of p_ will end immediately after that.
Moreover, there's no point in comparing p_ to null before calling delete, since delete expression performs this check internally. In your specific artificial example, the destructor should simply contain delete p_ and noting else. No if, no setting p_ to null.
In the case of p_, there is no need to set it equal to null in the destructor, but it can be a useful defensive mechanism. Imagine a case where you have a bug and something still holds a pointer to a B object after it has been deleted:
If it trys to delete the B object, p_ being null will cause that second delete to be innocuous rather than a heap corruptor.
If it trys to call a method on the B object, p_ being null will cause a crash immediately. If p_ is still the old value, the results are undefined and it may be hard to track down the cause of the resulting crash.