Basic Concept of Memory Management in a C++ Class

Have you ever paid attention to memory management when using classes? I have an elementary quiz about the basic concept of memory management in standard C++. This quiz is from my teaching experience because I found many programmers usually make the same mistake.

Now, take a look at the quiz. Please don't worry if you cannot give a answer. Paying attention to such code from now on is the most important thing you need to learn.

Quiz

How does the following code work?

What will happen during the running process? Why?

If there is a problem, how will you solve it?

class A
{
private:
   char* pchTest;
public:
   explicit A(char* const pchInitialText);
   virtual ~A();
   char* GetContent(void)const{return pchTest;}
};

A::A(char* const pchInitialText)
{
   pchTest = new char[strlen(pchInitialText)+1];
   strcpy(pchTest,pchInitialText);
}

A::~A()
{
   delete [] pchTest;
   pchTest = NULL;
}

void show(A clsAtest)
{
   printf("%s",clsAtest.GetContent());
}

int main(void)
{
   A Atest("Just Test!");
   show(Atest);
   return 0;
}

Hints

How is the parameter transferred into the functions as shown below?

void FunctionName(ValueType  para);
void FunctionName(ValueType *para);
void FunctionName(ValueType &para);

Have any idea? I will share my thoughts on the next page.

Basic Concept of Memory Management in a C++ Class

My Answer

First, let me explain the differences among the functions shown in the hints as on the last page:

  • For FunctionName(ValueType para), any value will be copied at first, and the copy is the real object accessed in the function. The original value would never be changed. The copy will be removed after the function ends.
  • For FunctionName(ValueType *para), the pointer will be copied at first. The copy pointer will be accessed in the function. The original value might be changed via the copy pointer. The copy pointer will be removed after the function ends, but the referred value won't be removed. For something like FunctionName(ValueType para), only the COPY will be removed.
  • For FunctionName(ValueType &para), no copying is done. The original object will be accessed directly in the function.

Now, let me go through the quiz code.

In main(), constructor A() is called; the pchTest member value of the Atest object is "Just Test!". Then, the Atest object is copied as clsAtest by the default copy constructor whenever the show() function is being called. The default constructor will copy only the value without allocating any memory automatically. That is, it will, by default, copy the value of Atest.pchTest to clsAtest.pchTest. Now, clsAtest.pchTest and Atest.pchTest point to the same memory. Then, the process displays "Just Test!" and clsAtest is removed at the end of show(), of course. So, the ~A() destructor is called.

Do you see the problem? The clsAtest.pchTest is deleted, and so is the memory that clsAtest.pchTest points to; that is also referred to by Atest.pchTest, but Atest is still alive! Now, Atest.pchTest actually points to an invalid memory! When the process exits main(), Atest will be deleted; the memory refered by Atest.pchTest will be deleted again. A memory error has occurred.

I think you might have some solutions now. Here, I share my three solutions; two are temporary solutions and one is a permanent cure.

Temporary solution 1: Use a pointer

void show(A *clsAtest)
{
   printf("%s",clsAtest->GetContent());
}

void main()
{
   A Atest("Just Test!");
   show(&Atest);
   return 0;
}

A pointer that refers to the Atest object will be copied; call it pAtest. Then, pAtest is accessed in show(). pAtest will be removed later, but the memory referred to by pAtest won't be deleted. Atest.pchTest still keeps the valid memory.

Temporary solution 2: Use a reference

void show(A &clsAtest)
{
   printf("%s",clsAtest.GetContent());
}

void main()
{
   A Atest("Just Test!");
   show(Atest);
 return 0;
}

This solution neither copies before entering the functions nor removes when the function ends. The process accesses the Atest object itself in the functions. If you don't want to modify any member value, use const, as shown below:

void show(const A & clsAtest)

Permanent cure

First, add a copy constructor:

A::A(const A &SourceA)
{
   pchTest = new char[strlen(SourceA.pchTest)+1];
   strcpy(pchTest,SourceA.pchTest);
}

When the process copies Atest, a copy constructor will be called so that cpA has its own pointer (cpA.pchTest), and its own memory referred to by cpA.pchTest. When the process exits show(), it deletes the memory that belongs to cpA, but not to Atest. No matter which kind of function has been called, no system error would occurr.

The same resource management issues will also occur in an assignment; for example:

void main()
{
   A Atest("Just Test!");
   A Atest2("Test Again!");
   Atest = Atest2;
   show(Atest);
   return 0;
}

Thus, you need to override the assignment operator:

A& A::operator= (const A &SourceA)
{
   if( this != &SourceA )
   {
      delete [] pchText;
      pchText = new char[strlen(SourceA.pchText)+1];
      strcpy(pchText,SourceA.pchText);
   }
   return *this;
}

The entire permanent cure code is on the next page.

Basic Concept of Memory Management in a C++ Class

#include <string.h>

class A
{
private:
   char* pchText;

public:
   explicit A(char* const pchInitialText);
   virtual ~A();
   A(const A &SourceA);
   A& operator= (const A &SourceA);

   char* GetContent(void)const{return pchText;}
};

A::A(char* const pchInitialText)
{
   pchText = new char[strlen(pchInitialText)+1];
   strcpy(pchText,pchInitialText);
}

A::~A()
{
   delete [] pchText;
   pchText = NULL;
}

A::A(const A &SourceA)
{
   pchText = new char[strlen(SourceA.pchText)+1];
   strcpy(pchText,SourceA.pchText);
}

A& A::operator= (const A &SourceA)
{
   if( this != &SourceA )
   {
      delete [] pchText;
      pchText = new char[strlen(SourceA.pchText)+1];
      strcpy(pchText,SourceA.pchText);
   }
   return *this;
}

void show(A clsAtest)
{
   printf("%s",clsAtest.GetContent());
}

int main(void)
{
   A Atest("Just Test");
   show(Atest);
   return 0;
}

Thank you for reading patiently. I hope this helps.

References



About the Author

Reta Pan

A R&D Software Engineer in Taiwan.
International High IQ Society Member, New York.
MCSD(Microsoft Certified Solution Developer (for Microsoft .NET))
Web Site: Anpino's Circle
English is not my primary language, I will be glad to receive your response, especially the advises that you can provide regarding my poor English.

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • CentreCorp is a fully integrated and diversified property management and real estate service company, specializing in the "shopping center" segment, and is one of the premier retail service providers in North America. Company executives travel a great deal, carrying a number of traveling laptops with critical current business data, and no easy way to back up to the network outside the office. Read this case study to learn how CentreCorp implemented a suite of business continuity services that included …

Most Popular Programming Stories

More for Developers

RSS Feeds