Answers/Solutions to Exercises in Chapter 10, Exercise 2

E2: Create as simple as possible a C or C++ based program exhibiting the undetermined ownership problem. Then rectify it using smart pointers.

S2: How many times I have seen something like this (continuation from Exercise 1):

....
....
// function DisplayMessage -----------------------------------
void DisplayMessage(int a1,float a2,char* tag)
{
  char *message;
  message=(char*)malloc(150+strlen(tag));
  // create the message
  ...
  // do something
  ...
  // do something
  if (tag==0)
    sprintf(message,"there are %d items with price %f without a tag\n",a1,a2);
  else
    sprintf(message,"there are %d items with price %f with tag %s\n",a1,a2,Interpret(tag));
  // display the message
  WriteLog(log,message);
  free((void*)message);
}
....
....
// function Interpret ------------------------------------------
char* Interpret(char *tag)
{
  static char buff[80];
  if (strcmp(tag,"tag1")==0)
     strcpy(buff,"Red tag without dot");
  else if (strcmp(tag,"tg2")==0)
     strcpy(buff,"Green tag with dot");
  strcat(buff,global_text);
  return buff;
} 

Of course, the problems pointed to in Exercise 1 were rectified by deallocation of message in DisplayMessage(). The program works OK until one day the programmer encounters a problem with the global variable global_text that causes an overflow of the buffer buff. An obvious "good" solution to the problem to use dynamic allocation was immediately implemented by the programmer:

// function Interpret ------------------------------------------
char* Interpret(char *tag)
{
  char *buff;
  buff = (chat*) malloc(strlen(global_text)+50);
  if (strcmp(tag,"tag1")==0)
     strcpy(buff,"Red tag without dot");
  else if (strcmp(tag,"tg2")==0)
     strcpy(buff,"Green tag with dot");
  strcat(buff,global_text);
  return buff;
} 

Of course, buff cannot be deallocated in Interpret, as it has to be returned to the caller. Of course, the caller has never bothered to deallocate the interpretation of t tag before (in fact it must not have been deallocated), so we have a classical example of poor interproject communication resulting in undetermined ownership problem: who is the owner of the segment --- the creator Interpret() or the caller and user DisplayMessage()?

Fixing it with smart pointers:

class SmartCharPtr
{
public:
	SmartCharPtr() { ptr=0; owner=0; }
	~SmartCharPtr() { 
		if (ptr!=0 && owner) 
			free((void*)ptr); 
	}
	SmartCharPtr& operator=(SmartCharPtr& p) { // pass along the ownership
		if (ptr!=0) free((void*)ptr);
		ptr=p.ptr;
		owner=1;
		p.owner=0;
		return *this;
	}
	SmartCharPtr& operator=(char* p) {  // obtain the original ownership
		if (ptr!=0) free((void*)ptr);
		ptr=p;
		owner=1;
		return *this;
	}
	operator char* () { return ptr; }

protected:
	char* ptr;
	int owner;
};

// function DisplayMessage -----------------------------------
void DisplayMessage(int a1,float a2,char* tag)
{
  char *message;
  SmartCharPtr p, q;
  message=(char*)malloc(150+strlen(tag));
  // create the message
  if (tag!=0) 
	  p=Interpret(tag);  // ownership passed from Interpret() to p
  // do something
  q = p;                     // ownership passed from p to q
  // do something
  if (tag==0)
    sprintf(message,"there are %d items with price %f without a tag\n",a1,a2);
  else
    sprintf(message,"there are %d items with price %f with tag %s\n",a1,a2,(char*)q);
  // display the message
  WriteLog(log,message);
  free((void*)message);
}
// when DisplayMessage() terminates, both p and q go out of scope, p will be destroyed without
// deallocating ptr as it is not owner, q will be destroyed with deallocating ptr, as it is owner
// function Interpret ------------------------------------------
SmartCharPtr& Interpret(char *tag)
{
  char *buff;
  static SmartCharPtr p;
  buff=(char*)malloc(150+strlen(global_text));
  if (strcmp(tag,"tag1")==0)
     strcpy(buff,"Red tag without dot");
  else if (strcmp(tag,"tag2")==0)
     strcpy(buff,"Green tag with dot");
  strcat(buff,global_text);
  p = buff;
  return p;
} 

Back to Answers/Solutions Index                          Back to Answers/Solutions for Chapter 10 Index