How to safely delete multiple pointers - c++

I have got some code which uses a lot of pointers pointing to the same address.
Given a equivalent simple example:
int *p = new int(1);
int *q = p;
int *r = q;
delete r; r = NULL; // ok
// delete q; q = NULL; // NOT ok
// delete p; p = NULL; // NOT ok
How to safely delete it without multiple delete?
This is especially difficult if I have a lot of objects which having pointers all pointing to the same address.

Your tool is shared_ptr of the boost library. Take a look at the documentation: http://www.boost.org/doc/libs/1_44_0/libs/smart_ptr/shared_ptr.htm
Example:
void func() {
boost::shared_ptr<int> p(new int(10));
boost::shared_ptr<int> q(p);
boost::shared_ptr<int> r(q);
// will be destructed correctly when they go out of scope.
}

The answer, without resorting to managed pointers, is that you should know whether or not to delete a pointer based on where it was allocated.
Your example is kind of contrived, but in a real world application, the object responsible for allocating memory would be responsible for destroying it. Methods and functions which receive already initialized pointers and store them for a time do not delete those pointers; that responsibility lies with whatever object originally allocated the memory.
Just remember that your calls to new should be balanced by your calls to delete. Every time you allocate memory, you know you have to write balancing code (often a destructor) to deallocate that memory.

The "modern" answer is to use a smart pointer and don't do any manual deletes.
boost::shared_ptr<int> p(new int(1));
boost::shared_ptr<int> q = p;
boost::shared_ptr<int> r = q;
End of story!

The problem you are facing is that the ownership semantics in your program are not clear. From a design point of view, try to determine who is the owner of the objects at each step. In many cases that will imply that whoever creates the object will have to delete it later on, but in other cases ownership can be transferred or even shared.
Once you know who owns the memory, then go back to code and implement it. If an object is the sole responsible for a different object, the it should hold it through a single-ownership smart pointer (std::auto_ptr/unique_ptr) or even a raw pointer (try to avoid this as it is a common source of errors) and manage the memory manually. Then pass references or pointers to other objects. When ownership is transfered use the smart pointer facilities to yield the object to the new owner. If the ownership is truly shared (there is no clear owner of the allocated object) then you can use shared_ptr and let the smart pointer deal with the memory management).

Why are you trying to delete pointers arbitrarily? Every dynamically allocated object is allocated in one place, by one owner. And it should be that one owners responsibility to ensure the object is deleted again.
In some cases, you may want to transfer ownership to another object or component, in which case the responsibility for deleting also changes.
And sometimes, you just want to forget about ownership and use shared ownership: everyone who uses the object shares ownersip, and as long as at least one user exists, the object should not be deleted.
Then you use shared_ptr.
In short, use RAII. Don't try to manually delete objects.

There are some very rare cases where you might not be able to use a smart pointer (probably dealing with old code), but cannot use a simple "ownership" scheme either.
Imagine you have an std::vector<whatever*> and some of the whatever* pointers point to the same object. Safe cleanup involves ensuring you don't delete the same whatever twice - so build an std::set<whatever*> as you go, and only delete the pointers that aren't already in the set. Once all the pointed-to objects have been deleted, both containers can safely be deleted as well.
The return value from insert can be used to determine whether the inserted item was new or not. I haven't tested the following (or used std::set for a while) but I think the following is right...
if (myset.insert (pointervalue).second)
{
// Value was successfully inserted as a new item
delete pointervalue;
}
You shouldn't design projects so that this is necessary, of course, but it's not too hard to deal with the situation if you can't avoid it.

It is not possible to know whether the memory referenced by a pointer has already been deleted, as in your case.
If you can not use a library with smart pointers, that do reference counting, and you can not implement your own reference counting schema (if indeed you need to do what you describe in your post) try to call realloc on the pointers.
I have read in other posts that depending on the implementation the call to realloc may not crash but return back a null pointer. In this case you know that the memory referenced by that pointer has been freed.
If this works as a dirty solution, it will not be portable, but if you have no other option, try it. The worse of course will be to crash your application :)

I would say that some times, smart pointers can actually slow down your application, albiet not by a lot. What I would do is create a method, like so:
void safeDelete(void **ptr)
{
if(*ptr != NULL)
{
delete ptr;
*ptr = NULL;
}
}
I'm not sure if I did it 100% correctly, but what you do is you pass the pointer into this method that takes the pointer of a pointer, checks to make sure the pointer it points to isn't set to NULL, then deletes the object and then sets the address to 0, or NULL. Correct me if this isn't a good way of doing this, I'm also new to this and someone told me this was a great way of checking without getting complicated.

Related

A pointer that can point to anywhere, how to determine if "delete" can be safely called on it?

Is there any way to distinguish two following situations at run time:
double ptr * = new double(3.14159);
double variable = 3.14159
double * testPtr_1 = ptr;
double * testPtr_2 = &variable;
delete testPtr_1 // fine...
delete testPtr_2 // BIG RUN TIME ERROR !!!
I have find myself in situation in with I need to call delete operator for some unknown pointer. The pointer can point to anywhere (to a "local" variable or to dynamically allocated variable).
How can I find out where my "unknown" pointer points, and therefore choose when to and when not to call operator delete on it
EDIT:
Ok I see that everyone is pointing me to the smart pointers, but what if I am trying to write my own set of smart pointers (that is The reason behind my question)?
There is no way to test if a pointer is pointing to a memory area that would be valid to delete. Moreover,
There is no way to tell between pointers that must be freed with delete vs. delete[],
There is no way to tell between the pointers that have been freed and pointers that have not been freed,
There is no way to tell among pointers to an automatic variable, pointers to static variable, and pointers to dynamically allocated blocks.
The approach that you should take is tracking allocations/deallocations by some other means, such as storing flags along with your pointers. However, this is rather tedious: a much better practice is to switch to smart pointers, which would track resources for you.
You need to set some better coding practices for yourself (or for your project).
Especially since most platforms have, at the very least, a C++11-compliant compiler, there's no reason not to be using the following paradigm:
Raw Pointers (T*) should ONLY be used as non-owning pointers. If you receive a T* as the input for a function or constructor, you should assume you have no responsibility for deleting it. If you have an instance or local variable that is a T*, you should assume you have no responsibility for deleting it.
Unique Pointers (std::unique_ptr<T>) should be used as single-ownership pointers, and in general, these should be your default go-to choice for any situation where you need to dynamically allocate memory. std::make_unique<T>() should be preferred for creating any kind of Unique Pointer, as this prevents you from ever seeing the raw pointer in use, and it prevents issues like you described in your original post.
Shared Pointers (std::shared_ptr<T> and std::weak_ptr<T>) should ONLY be used in situations where it is logically correct to have multiple owners of an object. These situations occur less often than you think, by the way! std::make_shared<T>() is the preferred method of creating Shared Pointers, for the same reasons as std::make_unique, and also because std::make_shared can perform some optimizations on the allocations, improving performance.
Vectors (std::vector<T>) should be used in situations where you need to allocate multiple objects into heap space, the same as if you called new T[size]. There's no reason to use pointers at all except in very exotic situations.
It should go without saying that you need to take my rules of "ONLY do 'x'" with a grain of salt: Occasionally, you will have to break those rules, and you might be in a situation where you need a different set of rules. But for 99% of use-cases, those rules are correct and will best convey the semantics you need to prevent memory leaks and properly reason about the behavior of your code.
You cannot.
Avoid raw pointers and use smart pointers, particularly std::unique_ptr. It conveys clearly who is responsible for deleting the object, and the object will be deleted when the std::unique_ptr goes out of scope.
When creating objects, avoid using new. Wrap them in a smart pointer directly and do not take addresses of anything to wrap it in a smart pointer. This way, all raw pointers will never need freeing and all smart pointers will get cleaned up properly when their time has come.
Okay, some things you can distinguish in a very platform-specific, implementation-defined manner. I won’t go into details here, because it’s essentially insane to do (and, again, depends on the platform and implementation), but you are asking for it.
Distinguish local, global and heap variables. This is actually possible on many modern architectures, simply because those three are different ranges of the address space. Global variables live in the data section (as defined by the linker and run-time loader), local variables on the stack (usually at the end of the address space) and heap variables live in memory obtained during run-time (usually not at the end of the address space and of course not overlapping the data and code sections, a.k.a. "mostly everything else"). The memory allocator knows which range that is and can tell you details about the blocks in there, see below.
Detect already-freed variables: you can ask the memory allocator that, possibly by inspecting its state. You can even find out when a pointer points into a allocated region and then find out the block to which it belongs. This is however probably computationally expensive to do.
Distinguishing heap and stack is a bit tricky. If your stack grows large and your program is running long and some piece of heap has been returned to the OS, it is possible that an address which formerly belonged to the heap now belongs to the stack (and the opposite may be possible too). So as I mentioned, it is insane to do this.
You can't reliably. This is why owning raw pointers are dangerous, they do not couple the lifetime to the pointer but instead leave it up to you the programmers to know all the things that could happen and prepare for them all.
This is why we have smart pointers now. These pointers couple the life time to the pointer which means the pointer is only deleted once it is no longer in use anywhere. This makes dealing with pointer much more manageable.
The cpp core guildlines suggests that a raw pointer should never be deleted as it is just a view. You are just using it like a reference and it's lifetime is managed by something else.
Ok I see that everyone is pointing me to the smart pointers, but what if I am trying to write my own set of smart pointers (that is The reason behind my question)?
In that case do like the standard smart pointers do and take a deleter which you default to just using delete. That way if the user of the class wants to pass in a pointer to a stack object they can specify a do nothing deleter and you smart pointer will use that and, well, do nothing. This puts the onus on the person using the smart pointer to tell the pointer how to delete what it points to. Normally they will never need to use something other than the default but if they happen to use a custom allocator and need to use a custom deallocator they can do so using this method.
Actually you can. But memory overhead occurs.
You overload new and delete operator and then keep track of allocations and store it somewhere(void *)
#include<iostream>
#include<algorithm>
using namespace std;
void** memoryTrack=(void **)malloc(sizeof(void *)*100); //This will store address of newly allocated memory by new operator(really malloc)
int cnt=0;//just to count
//New operator overloaded
void *operator new( size_t stAllocateBlock ) {
cout<<"in new";
void *ptr = malloc(stAllocateBlock); //Allocate memory using malloc
memoryTrack[cnt] = ptr;//Store it in our memoryTrack
cnt++; //Increment counter
return ptr; //return address generated by malloc
}
void display()
{
for(int i=0;i<cnt;i++)
cout<<memoryTrack[i]<<endl;
}
int main()
{
double *ptr = new double(3.14159);
double variable = 3.14159;
double * testPtr_1 = ptr;
double * testPtr_2 = &variable;
delete testPtr_1; // fine...
delete testPtr_2;
return 0;
}
Now the most important function(You will have to work on this because it is not complete)
void operator delete( void *pvMem )
{
//Just printing the address to be searched in our memoryTrack
cout<<pvMem<<endl;
//If found free the memory
if(find(memoryTrack,memoryTrack+cnt,pvMem)!=memoryTrack+cnt)
{
//cout<<*(find(memoryTrack,memoryTrack+cnt,pvMem));
cout<<"Can be deleted\n";
free (pvMem);
//After this make that location of memoryTrack as NULL
//Also keep track of indices that are NULL
//So that you can insert next address there
//Or better yet implement linked list(Sorry was too lazy to do)
}
else
cout<<"Don't delete memory that was not allocated by you\n";
}
Output
in new
0xde1360
0xde1360
Can be deleted
0xde1360
0x7ffe4fa33f08
Dont delete memory that was not allocated by you
0xde1360
Important Node
This is just basics and just code to get you started
Open for others to edit and make necessary changes/optimization
Cannot use STL, they use new operator(if some can implement them please do,it would help to reduce and optimize the code)

Equivalent implementation of unique_ptr::reset for raw pointers?

I'm trying to refactor a section of code into a separate object/file. To maintain the same behavior, my code needs to use pointers to key components in the original file, which are declared as unique_ptrs.
I was thinking to extract the raw pointers and pass them to my object since my portion isn't responsible for deleting any pointers. (I hope I'm understanding ownership semantics correctly, still relatively new to C++). The only caveat is that I need to replicate unique_ptr::reset's behavior. Will this code do the same thing reset does?
template <typename Type>
void reset(Type* &current_ptr){
Type* old_ptr = current_ptr;
current_ptr = new Type();
if(old_ptr != null)
delete old_ptr;
}
If you need to call reset then you are in fact actually deleting pointers, and doing so outside the context of the unique_ptr's destructor is a recipe asking for disaster (even if your code appears to work it may still be undefined behavior).
If in fact all you need is to dereference (primarily * and ->) the unique_ptr then you should pass and use a reference to the object in your new code, making sure that the unique_ptr can't die while you're using the reference.
If you need to reassign or reset the smart pointer you'll need an alternate approach, but you didn't supply enough information in the question to help scope out such an alternate approach.
No, that's not what reset() does.
As pointed out in the comments, the features of smart pointers are about ownership, not pointers themselves. Ownership means responsibility, so if a unique_ptr owns an object, it is its "job" to delete it when the unique_ptr dies itself. shared_ptr are a little more complex, but they are also all about deleting the object "when the time comes", and taking that responsibility off of you, the programmer.
unique_ptrs are unique, that is, no two unique_ptrs should ever own the same object.
Now, the reset() method is a way of saying "hey, unique_ptr, I've got a new pointer for you to manage, so destroy the old one (if you had any) and take ownership of this new one that I'm giving you. From now on, this is the one you'll destroy when you die yourself."
This operation has no meaning with raw pointers, since they do not hold any ownership and won't kill themselves off at the right time or anything like that.
So, comparing that with your code, the similarity is that the old pointer is indeed deleted. But apart from the essence being missing (that is, the raw pointer won't remember to delete itself and does not hold ownership), the normal reset() is given a pointer, it does not create a new object by itself.

Deleting memory when it was deleted before

I have a small C++ program where I create two objects of a Person class. This class has char *m_szFirstName and char *m_szLastName for data.
I then I assign one object to another, causing both object's data members to point to same location.
In the destructor, I delete what memory I had allocated for the first object and assign NULL values to the pointers. Something like this.
if (m_szFirstName!= NULL)
{
delete [] m_szFirstName;
m_szFirstName = NULL;
}
Then when I go to delete memory for the second object, the check for NULL does not work and when I delete memory, I get a crash. From debugger, it show that my pointer is not NULL. It has 0xfeee.
I am aware that memory was already deleted before and should not be delete. However, I don't know how to check whether I should delete memory or not.
Reason for Crash:
You should follow the Rule of Three to avoid this problem of dangling pointers.
If you need to explicitly declare either the destructor, copy constructor or copy assignment operator yourself, you probably need to explicitly declare all three of them.
In your case You do not define a copy assignment operator thus leading to shallow copy of the pointer.
Suggested Solution:
If you can use std::string instead of char * just simply use std::string, it has the first and foremost preference over any kind of silly pointer stuff.
You can avoid all the funky pointer stuff by using std::string.
If you can't read on and the following suggestion applies to any class pointer member in general.
Note that the ideal solution here is to not use raw pointers at all, Whenever you use raw pointers you are forced to manually manage the resources acquired by them, it is always difficult and error prone to manually manage resources.So the onus is to avoid it.
To do so, You should use a Smart pointer which will manage the dynamic memory of the pointer implicitly.Using a smart pointer will ensure that the dynamic memory is implicitly released after usage & you do not have to manually manage it.
The scenario you have is the very reason that in C++ you should rely on RAII rather than manual resource management & using a Smart pointer is the way to go about in your case.
Caveat:
Note that I restrained myself from suggesting which smart pointer to use because the choice rather depends on the ownership and lifetime of the elements involved, which is not clear from the data provided in the Question.So I will suggest reading,
Which kind of pointer do I use when?
to make your choice of the smart pointer to use.
With
if (m_szFirstName!= NULL)
{
delete [] m_szFirstName;
m_szFirstName = NULL;
}
You only set m_szFirstName to point to NULL, not m_szLastName. This means you have to have some way to keep track of the fact they point to the same location. Is there a reason they point to the same location? Could you copy the name instead of pointing the pointers to the same place?
If you need the two pointers to shared the same data, I would have a look at std::tr1::shared_ptr, which will solve this issue for you by keeping track of the number of references and deleting when the number of references reaches 0.
Don't delete it again, if (m_szFirstName == m_szLastName).
But this will give you a memory leak (when you assign one pointer to other).
When you have two pointers pointing to the same location (after you assigned the first one to the second one), you have two pointers pointing at the same address. Deleting one frees the memory pointed to by both of them. But setting one to NULL doesn't alter the other pointer. The same happens if you have two integers, for example.
int a = 3;
int b = a;
Now if you run
a = 0;
the value of b doesn't change. The same way your second pointer doesn't change when you alter the first one (but when you alter the memory pointed to by either pointer, you can see the effect through the other as well).
Your problem is a classic C/C++ problem which is known as "Dangling Pointer" problem. Dereferencing the dangling pointer has resulted in the crash. The problem is about reference counting. Once you assign the same memory to the second pointer then the reference count should be 2. So if you delete one pointer reference count should become 1 and your memory should not be deallocated or freed unless count is 0. At 0 it can be garbage collected.
Now there are good answers above to solve your problem. Since you are using C++ so you can use something like an auto_ptr (OR shared_ptr). They provide what I had mentioned above, the reference counting stuff and even you need not worry about deleting or freeing your objects, these classes would take care. They work on simething known as RAII pattern where a destructor is auto-magically called when the object on the stack goes out of scope.
Just stop setting pointers to NULL when you have deleted the object. As you can see, it just leads to pain. You cannot assume that because the pointer is not-NULL, it has not been deleted already.
You can use any sensible pattern you want to avoid this problem. For example, Boost's shared_ptr is a great choice.

C++ Confusion using delete when asigning a pointer to a pointer (and passing pointers to classes)

Sorry if my last question is very similar, but I have another query of when and if I should use the delete keyword.
Example code.
I initialize a class that has pointer to vector of pointers as their arguments. These objects are assigned memory from the heap. I then pass these objects to my class constructor which is also assigned memory from the heap.
Here is the code:
in the main function
//This will also change each loop
vector<A*>* ex1 = new vector<A*>;
vector<B*>* ex2 = new vector<B*>;
vector<C*>* ex3 = new vector<B*>;
for(int i =0; i < 10; i++){
ex1->push_back( new A(i); );
ex2->push_back( new B(i); );
ex3->push_back( new C(i); );
}
MainClass* ex_main = new MainClass(ex1,ex2,ex3);
inside MainClass.cxx
MainClass::MainClass(vector<A*>* ex_A, vector<B*>* ex_B, vector<C*>* ex_C): m_ex_A(ex_A), m_ex_B(ex_B), m_ex_C(ex_C) {}
inside MainClass.h
vector<A*>* m_ex_A;
vector<B*>* m_ex_B;
vector<C*>* m_ex_C;
m_ex1, m_ex2 and m_ex3 have been assigned to the stack, but have been assigned to the pointer to vector of pointers.
Questions.
Do I delete the m_ex_A,B ans C in the destructor of class MainClass (I know I will need to delete the elements in each vector as well) and also the pointer to vector of pointers in the main function?
e.x. in destructor of MainClass (I do something a bit more generic than this, but this is quicker to show )
for(int i = 0; i < m_ex_A->size(); i++){
delete m_ex_A->at(i);
}
delete m_ex_A;
I would then do a similar approach for pointer to vector of pointers ex1, ex2, ex3 in the main function and also delete the main class.
My confusion comes from the fact that m_ex_A,B and C are assigned to the Stack and not dynamically, but they get assigned to dynamic objects?
My guess would be to use delete to m_ex_A,B, C objects as I have dynamically initialized them?
Also what is more efficient using heap memory or stack??
I think I might be using dynamic memory to much...
You definitely should delete your dynamically allocated objects somewhere. Could as well do it it the destructor of MainClass, but personally, I'd consider it a bad style. Why? Because you're allocating and deleting in different places, in different entities. In fact, you're transferring ownership of these objects, so you should be very careful to not to delete twice or something. I'd rather use shared_ptr or unique_ptr and releave my mind of all this micromanagement. You can search those on the web, and they are extremely easy to use.
As for the second question - you MUST only delete every object once. Copying pointers doesn't create new object, it's just another pointer to the same object.
This is not a direct Answer to the question but trying to clear up the underlying issue:
The conceptual issue is that raw pointers do not convey (and worse have no way of) ownership information. They are just a pointer to a memory location.
Now, whenever you allocate dynamic memory with new you are responsible to delete it somewhere.
To decide where this somewhere is is part of designing your program. If you pass a pointer to some object like in your example you need to document if the object takes ownership of the passed in pointed to memory (in this case the object becomes responsible for cleanup) or if it does not (and the caller remains responsible).
With raw pointers there is no way of knowing (except for documentation or examining the implementation) whether or not any given function takes ownership.
This is where the new C++11 (also available from boost) smart pointers (unique_ptr and shared_ptr) fit in. They immediately convey who is responsible for deleting the memory and even better take care of doing so automatically (and with little- or in case of unique_ptr no- overhead)
So as a final guideline: Never ever use raw pointers instead of smart pointers or some other kind of RAII mechanism! (until you gain much more experience with those and can prove that raw pointers are in fact a better solution in that special case)

Memory leak issue; deleting a pointer

If I have a pointer pointing to a specific memory address at the heap. I would like this same pointer to point to another memory address, should I first delete the pointer? But, in this case am I actually deleting the pointer or just breaking the reference (memory address) the pointer is pointing at?
So, in other words, if I delete a pointer, does this mean it doesn't exist any more? Or, it is there, but not pointing to where it was?
The syntax of delete is a bit misleading. When you write
T* ptr = /* ... */
delete ptr;
You are not deleting the variable ptr. Instead, you are deleting the object that ptr points at. The value of ptr is unchanged and it still points where it used to, so you should be sure not to dereference it without first reassigning it.
There is no requirement that you delete a pointer before you reassign it. However, you should ensure that if you are about to reassign a pointer in a way that causes you to lose your last reference to the object being pointed at (for example, if this pointer is the only pointer in the program to its pointee), then you should delete it to ensure that you don't leak memory.
One technique many C++ programmers use to simplify the logic for when to free memory is to use smart pointers, objects that overload the operators necessary to mimic a pointer and that have custom code that executes automatically to help keep track of resources. The new C++0x standard, for example, will provide a shared_ptr and unique_ptr type for this purpose. shared_ptr acts like a regular pointer, except that it keeps track of how many shared_ptrs there are to a resource. When the last shared_ptr to a resource changes where it's pointing (either by being reassigned or by being destroyed), it then frees the resource. For example:
{
shared_ptr<int> myPtr(new int);
*myPtr = 137;
{
shared_ptr<int> myOtherPtr = myPtr;
*myPtr = 42;
}
}
Notice that nowhere in this code is there a call to delete to match the call to new! This is because the shared_ptr is smart enough to notice when the last pointer stops pointing to the resource.
There are a few idiosyncrasies to be aware of when using smart pointers, but they're well worth the time investment to learn about. You can write much cleaner code once you understand how they work.
When you delete a pointer you release the memory allocated to the pointed to object. So if you just want your pointer to point to a new memory location you should not delete the pointer. But if you want to destroy the object currently it is pointing to and then then point to a different object then you should delete the pointer.
xtofl, while being funny, is a bit correct.
If YOU 'new' a memory address, then you should delete it, otherwise leave it alone. Maybe you are thinking too much about it, but you think about it like this. Yea, the memory is always there, but if you put a fence around it, you need to take the fence down, or no one else can you it.
When you call delete you mark the memory pointed to by the pointer as free - the heap takes ownership of it and can reuse it, that's all, the pointer itself is usually unchanged.
What to do with the pointer depends on what you want. If you no longer need that memory block - use delete to free the block. If you need it later - store the address somewhere where you can retrieve it later.
To answer your question directly, this has been asked before. delete will delete what your pointer points to, but there was a suggestion by Bjarne Stroustrup that the value of the pointer itself can no longer be relied upon, particularly if it is an l-value. However that does not affect the ability to reassign it so this would be valid:
for( p = first; p != last; ++p )
{
delete p;
}
if you are iterating over an array of pointers, all of which had been allocated with new.
Memory management in C++ is best done with a technique called RAII, "resource acquisition is initialization".
What that actually means is that at the time you allocate the resource you immediately take care of its lifetime, i.e. you "manage" it by putting it inside some object that will delete it for you when it's no longer required.
shared_ptr is a technique commonly used where the resource will be used in many places and you do not know for certain which will be the last one to "release" it, i.e. no longer require it.
shared_ptr is often used in other places simply for its semantics, i.e. you can copy and assign them easily enough.
There are other memory management smart pointers, in particular std::auto_ptr which will be superceded by unique_ptr, and there is also scoped_ptr. weak_ptr is a methodology to be able to obtain a shared_ptr if one exists somewhere, but not holding a reference yourself. You call "lock()" which gives you a shared_ptr to memory or a NULL one if all the current shared pointers have gone.
For arrays, you would not normally use a smart pointer but simply use vector.
For strings you would normally use the string class rather than think of it as a vector of char.
In short, you do not "delete a pointer", you delete whatever the pointer points to.
This is a classical problem: If you delete it, and someone else is pointing to it, they will read garbage (and most likely crash your application). On the other hand, if you do not and this was the last pointer, your application will leak memory.
In addition, a pointer may point to thing that were not originally allocated by "new", e.g. a static variable, an object on the stack, or into the middle of another object. In all those cases you're not allowed to delete whatever the pointer points to.
Typically, when designing an application, you (yes, you) have to decide which part of the application owns a specific object. It, and only it, should delete the objects when it is done with it.