views:

79

answers:

6

Please have a glance at this program:

class CopyCon
{
public:
char *name;

CopyCon()
{ 
    name = new char[20];        
    name = "Hai";//_tcscpy(name,"Hai");
}

CopyCon(const CopyCon &objCopyCon)
{
    name = new char[_tcslen(objCopyCon.name)+1];
    _tcscpy(name,objCopyCon.name);
}

~CopyCon()
{
    if( name != NULL )
    {
        delete[] name;
        name = NULL;
    }
}
};

int main()
{
    CopyCon obj1;
    CopyCon obj2(obj1);
    cout<<obj1.name<<endl;
    cout<<obj2.name<<endl;
}

This program crashes on execution. Error: "Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)"

If I assign "Hai" to name using aasignment operator, its crashing. Where as when I use string func _tcscpy to assign "Hai" to name, its working perfectly. Can some one explain why so?

+2  A: 

When you use assignment, you make the pointer name point at the string literal "Hai". This later gets deleted in the destructor. However, the string literal was not allocated with new, and cannot be deleted like this, so you get undefined behaviour. You can only deallocate with delete things you allocated with new. This has nothing to do with the copy constructor.

anon
+4  A: 
 name = "Hai";//_tcscpy(name,"Hai");

You are not copying contents of "Hai" into name instead name will point to a read only memory ( whose contents are "Hai") if you try to delete name later then it might crash.

aJ
There is no more to say here.
fmuecke
Except that C++ makes no guarantee that "Hai" is stored in read-only memory.
anon
It makes a guarantee that calling delete[] on a string literal results uin undefined behaviour though.
Joe Gauterin
+3  A: 

In the default constructor

CopyCon()
{ 
    name = new char[20];        
    name = "Hai";//_tcscpy(name,"Hai");
}

you assign the address of a string literal to the pointer and in the destructor you call delete[] on it, that's undefined behavior. delete[] should only be called on addresses returned by new[].

When you instead use _tcscpy() you copy the literal content to the buffer allocated by new[] and then the destructor runs fine.

sharptooth
A: 

What you do in that code is that you allocate a memory block for the name (assign an address to name pointer). Then you actually overwrite this address by the address of the string literal "Hai" (which ceases to exist after the constructor finishes). Thats why you get the error, since the destructor tries to free memory which does not belong to you. ( You did not allocate it ).

PeterK
+2  A: 
name = new char[20];        
name = "Hai";//_tcscpy(name,"Hai");

Here you are not copying the data into the memory allocated by new. Instead you are assigning a new value to pointer name which points at read-only location (in most cases). Since this memory was not allocated using new you can not do delete on it. Also, note that you have a memory leak here as the memory allocated using new char[20]; is never deleted.

Naveen
+2  A: 

The very same program, but in C++:

struct CopyCon
{
  CopyCon(): name("HAI") {}
  std::string name;
};

int main(int argc, char* argv[])
{
  CopyCon obj1;
  CopyCon obj2(obj1);
  cout<<obj1.name<<endl;
  cout<<obj2.name<<endl;
}

Mine works, is clear, and I typed less than you did ;)

Matthieu M.
+1 for showing 'real' C++.
xtofl