views:

55

answers:

5

So I decided to dwelve a bit within the pesty C++.

When I call the delete function on a pointer to a simple class that I created I'm greeted by a Debug Assertion Failure -Expression:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse). I assume this is because I've handled the string manipulation wrong and thus causing memory corruption.

I created a basic class, [I]animal[/I], that has a string defined that can be set through a function.

// name
char * ptrName;

animal::animal(char * name)
{
 this->SetName(name);
};

animal::~animal()
{
 delete [] ptrName;
}

void animal::SetName(char * name)
{
 ptrName = name;
};

When using the above class as shown below the error occurs. I've tried both delete ptrName and delete [] ptrName but to no avail.

animal * cat = new animal("Optimus Prime");
delete cat;

What am I missing?

+1  A: 

Who has ownership of your string?

For example, when you construct your new animal, you're passing in a string literal - that's not yours to free.

You should consider avoiding char* and just using std::string instead.

If you have to use char*, think about ownership. For example, one option is for you to take a copy of the string (using strdup) and own that. This way you can't be stuck with strange bugs like this

char* szFoo = strdup("my string");
{
  animal a(szFoo);
}
// At this point szFoo has been deleted by the destructor of a
// and bad things will start to happen here.
printf("The value of my string %s",szFoo);
Jeff Foster
+1  A: 

The string "Optimus Prime" was not dynamically allocated, and thus it is not correct to call delete on it.

JaredReisinger
+2  A: 

The problem comes from deleting a pointer that you don't own. You haven't allocated the string, so you must not delete it. The C string you are using is allocated statically by the compiler.

David
+2  A: 

The problem is that in the setName function you are merely assigning the name to ptrName. In the example, the name is a const char string pointer which you can't delete (it is not allocated on the heap). To avoid this error, you can either use a std::string in the class or allocate a new char arry in the constructor of the animal class and assign the pointer to it. Then, in the destructor you can delete the array.

Gangadhar
+1  A: 

So I decided to dwelve a bit within the pesty C++.

Then do yourself a favor and use C++ right. That would be to use std::string:

// name
std::string name_;

animal::animal(const std::string& name)
  : name_(name)
{
}

//animal::~animal() // not needed any longer

//note: copying also automatically taken care of by std::string
//animal(const animal&)
//animal& operator=(const animal&)

void animal::SetName(const std::string& name)
{
 name_ = name;
}

Have a look at The Definitive C++ Book Guide and List. I'd recommend Accelerated C++. It comes with a steep learning curve, but since you already know a bit of C++, it's the 250 pages that might set you on the right track.

As a rule of thumb: Whenever you release a resource (memory or other), and it's not in the destructor of a class whose solely purpose is to manage this one resource, something is wrong with your design. Personally, I become suspicious whenever I feel the need to write a destructor, copy constructor, or assignment operator.

sbi
I ordered Accelerated C++ from Amazon just now. What is the reason for not needing to deallocate the name_ variable when you set it to a new value?
Qua
All the logic of allocating and deallocating is hidden behind std::string.
Jeff Foster
@Qua: When it's `std::string`, then that class takes care of memory management for you. When it's C strings (pointers to the first character of a dynamically allocated array), you have to do it manually. But then you also have to keep track of which pointer really points to a dynamically allocated array.A string literal isn't dynamically allocated, so it doesn't need to be `delete[]`'d. But inside of your class you don't know whether a pointer handed in points to a dynamically allocated array. So you have to always copy it into your own array and leave...
sbi
...managing the pointer handed in to the caller. The fact that this is error-prone is one of the main reasons C++ with its abstraction mechanisms was invented in the first place. I suppose a string class was among the first dozen of classes ever written for C++. Now that we have `std::string` just use that.
sbi
Excellent insight into topics that aren't that dominant in the world of .NET.
Qua