class name {
    char *s;
    int len;

public:

    name(){             // Default constr.
        s=NULL;
        len =0;
    }

    //**************************************************

     ~name(){           //  Destruct.
         if (s!=NULL){
             delete [] s;
             s=NULL;
         }
     }

     //*************************************************

    name(const char * s1);      // Constr.

    char* getName();    //fcn get name
    int getLen() ;       // fcn get lenght 
    void setName(const char * s1); // fcn set name  



};

void name::setName(const char * s1){

    if (s!=NULL){
        delete [] s;
            s=NULL;
    } 

        len = strlen(s1)+1;
        s=new char [len];  // back***
        strcpy(s,s1);

}


name::name(const char * s1){

    if (s!=NULL){
        delete [] s;
            s=NULL;
    } 

        len = strlen(s1)+1;
        s=new char [len];  // back***
        strcpy(s,s1);

}

char* name::getName(){

    return s ;

}
int name::getLen(){

    return strlen(s)+1 ;

}


int main()
{
    char C[20];
    cout << "Please enter a name: ";
    cin >> C;

    name AAA(C);

    name BBB;
    BBB.setName(C);

    cout << "\nThe length of A(" << AAA.getName();
    cout << ") is: \a" << AAA.getLen() << endl << endl;

    cout << "\nThe length of B(" << BBB.getName();
    cout << ") is: \a" << BBB.getLen() << endl << endl;

    system("pause");

    return 0;
}

when i run the code , the class "BBB" execute successfully but "AAA" give me runtime error !!

** error desc. :**

Unhandled exception at 0x651157aa (msvcr100d.dll) in test0.exe: 0xC0000005: Access violation reading location 0xccccccc0.

Why are you not including the following:

#include <iostream>
using namespace std; 

It compiles fine entering ^^ on GCC

Access violation reading location 0xccccccc0.

The popular compiler from Microsoft uses the value 0xcccccccc to indicate a value on the stack that you never set to anything (i.e. uninitialised stack memory). The obvious conclusion here is that you are using a pointer that you never set to any value.

Let's look at your code.

The non-default constructor for the class name is called, like this:name AAA(C); . What happens?

name::name(const char * s1){
    if (s!=NULL){
            delete [] s;
                s=NULL;
                } 

What's s right now? Is it NULL? Did it ever get set to NULL? No, it did not. It was never set to anything. So it's probably not NULL, so this code delete [] s; is going to be executed. Uh oh! We're going to call delete on s, but s doesn't point at memory that was allocated by new. s is just some uninitialised pointer on the stack. What value do uninitialised variables on the stack have in your system? Why,they have the value 0xcccccccc. So everything indicates that this is the problem. You're calling delete on s, but you never set s to anything.

Your non-default constructor is broken. It checks values of its member variables before setting them to anything.

Bonus answer: Why does your code try to access memory location 0xccccccc0? Because when you allocate an array using new, some information about that array is stored right before the array memory, so when you call delete on location 0xcccccccc, which is what your code does, delete goes looking in a location a few bytes before where the pointer is pointing to - in this case, location 0xccccccc0.

Edited 3 Years Ago by Moschops

Look in the constructor name::name(const char* s1) this is what you do:

name::name(const char * s1){
    if (s!=NULL)
    {
        delete [] s;
        s=NULL;
    } 
    len = strlen(s1)+1;
    s=new char [len];  // back***
    strcpy(s,s1);
}

Do this instead:

    name::name(const char * s1)
    : s(0),
      len(0)
    {
        if (s1)
        {
            len = ::strlen(s1)+1;
            s=new char[len];  // back***
            ::strcpy(s,s1);
        }
    }

Note the use of the initializers before the body of the constructor - you also should do this in the default constructor. Also, since the s and len variable values are 0, you don't want to test/delete here. It makes sense in the setName() method, but not here... :-)

Also note my use of the :: leader for C library calls (strlen, strcpy, et al). That will make sure that the C library functions are used, and not a possible class method of the same name!

Edited 3 Years Ago by rubberman

Moschops , Thank you for the excellent explanation.
The problem is well understood , just one question : when i call non-default constructer ,is the default constructer called ?

when i call non-default constructer ,is the default constructer called ?

No.

In C++ 11 you can call the default constructor from another constructor if you want to, but you have to do it.

This article has been dead for over six months. Start a new discussion instead.