Sign in to follow this  

auto_ptr triggers heap corruption when deleting std::string

This topic is 2581 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello. I'm trying to implement my own smart pointer class for learning purposes. As a solution to circular referencing, I made a static array that holds all pointers wrapped in std::auto_ptr, which releases the pointers that still exist on application exiting. However, that doesn't work and triggers a heap corruption error. Here is the code I think is relevant:

template <class T>
class sptr
{
public:
//parametrized constructor
//this is the constructor that should be used to wrap new pointers
sptr(T* new_ptr=0)
{
register_ptr(new_ptr);
}
//copy constructor
sptr(const sptr& sptr)
{
register_ptr(sptr);
}
//destructor
~sptr(void)
{
release_ptr();
}
/*
There is also a bunch of accessors and overloaded operators that I didn't include.
*/

private:
typedef std::pair<std::auto_ptr<T>, std::auto_ptr<int>> ptr_pair;
typedef std::vector<ptr_pair> pair_array;
//the pointer
T* ptr;
//its reference counter
int* ref_ctr;
friend class sptr;
//this is the array that stores information about all pointers and their reference counters
//note that all pointers are wrapped in std::auto_ptr
//this is in case the sptr won't be able to release pointers due to cyclic referencing
static pair_array allptrs;
//the release function used to destroy the ptr as to prevent memory leaks.
void release_ptr()
{
//if the ptr is not set, then this is an empty wrapper
if(exists(ptr))
{
(*ref_ctr)--;
//if the ref_ctr is 0, then that is the last instance of this pointer's wrapper
//so everything must be deleted
if((*ref_ctr)==0)
remove(ptr);
//allptrs.erase(allptrs.begin()+getPtrId(ptr));
}
}
//the helper wrapping function that is used to automatically release the old ptr and set new one upon any change
//if this function is used to wrap a completely new ptr, last param is not filled
void wrap_ptr(T* new_ptr)
{
if(new_ptr!=ptr)
{
//release the old ptr before changing anything
release_ptr();
//set the new one
register_ptr(new_ptr);
}
}
//this function can only be used twice outside of wrap_ptr - in the constructors
void register_ptr(T* new_ptr)
{
if(new_ptr)
{
ptr=new_ptr;
//if the pointer does actually exist in the allptrs array
if(exists(ptr))
{
ptr_pair pair=getPair(ptr);
//just grab the ref_ctr from it
ref_ctr=pair.second.get();
}
//if the pointer is new
else
{
//create a new ref counter
ref_ctr=new int(0);
//store both the ptr and the ref_ctr in the allptrs array for further use
allptrs.push_back(ptr_pair(std::auto_ptr<T>(ptr), std::auto_ptr<int>(ref_ctr)));
//allptrs.back().first.reset(ptr);
//allptrs.back().second.reset(ref_ctr);
}
(*ref_ctr)++;
}
else
{
ptr=0;
ref_ctr=0;
}
}
//the find function for the sptr class
bool exists(T* p)
{
if(p)
for(pair_array::iterator it=allptrs.begin(); it!=allptrs.end(); it++)
if((*it).first.get()==p)
return true;
return false;
}
void remove(T* p)
{
for(pair_array::iterator it=allptrs.begin(); it!=allptrs.end(); it++)
if((*it).first.get()==p)
{
allptrs.erase(it);
break;
}
}
ptr_pair getPair(T* p)
{

for(pair_array::iterator it=allptrs.begin(); it!=allptrs.end(); it++)
if((*it).first.get()==p)
return *it;
throw null_ptr_exception();
}
};
//initialise the static vector variable
template<typename T>
std::vector<std::pair<std::auto_ptr<T>, std::auto_ptr<int>>> sptr<T>::allptrs=std::vector<std::pair<std::auto_ptr<T>, std::auto_ptr<int>>>();



The heap corruption is reported after leaving the scope of this function:

void ResourceMan::AddSkill(string name)
{
sptr<Skill> skill=sptr<Skill>(new Skill());
skill->Name=name;
Skills.push_back(skill);
}



Those problems began when I implemented the circular referencing functionality for my pointers. As far as I understand, heap corruption occurs when one is trying to delete an object on a different heap that it was created on. My guess is that it is triggered on release of the "name" local variable. However, I can not really see how it is linked to sptr class in any way. I'm really confused at what is happening. Is my implementation of sptr correct? Or is there something that I'm doing that I'm not supposed to do? Or is sptr even the cause of the heap corruption?

Share this post


Link to post
Share on other sites
Heap corruption occurs when the bookkeeping structures for dynamic memory get corrupted. It can happen when freeing memory in the wrong heap, freeing memory twice, freeing memory that wasn't actually allocated, writing past the end of allocated memory, writing before the beginning of allocated memory, writing to freed memory or any number of other reasons involving bad pointer use.

That said, storing std::auto_ptrs in a std::vector is undefined behavior. I'm actually pretty surprised that your code even compiles.

Share this post


Link to post
Share on other sites
I see. Thank you for clarifying that. However, is there a way for me to implement sptr with circular references without using auto_ptrs? I want my allptrs array to automatically clean its contents up upon its deletion. This way any circular referencing will die upon program exiting.

Share this post


Link to post
Share on other sites

This topic is 2581 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this