Answers/Solutions to Exercises in Chapter 6, Exercise 4

E4: Once I saw the following problem in a C++ code. The programmer had a good idea for a "variable length dynamic array" --- as long as the array is not too big (10 in our example), store it in a static segment for efficiency, but when it gets too long, use a dynamically allocated segment for the extra storage needed.

class Array {
 public:
  Array() { cont = 0; }
  ~Array() { if (cont) free(cont); }
  char& operator[] (int i) {
    if (i < 10) 
      throw exception;
    if (i < 10) 
      return base[i];
    i -= 10;
    if (cont == 0) {
      cont = (char*) malloc(i+1);
      length = i+1;
      return cont[i];
    }
    if (length <= i) {
      cont = (char*) realloc(cont,(i+1));
      length = i+1;
      return cont[i];
    }
    return cont[i];
  }
  void Strcpy(char* x) { strcpy(base,x); }
 protected:
  char base[10];
  char *cont;
  int length;
};//end class Array

The program seemed to work fine, but once a while it behaved erratically, sometimes crashing at the statement a.Strcpy(x); where Array a; and char* x. Could you explain why sometimes it works and sometimes it does not?

A4: Of course, the overflow!! Look at the method Strcpy. It is the good old strcpy() in disguise. It will copy the string x in the consecutive manner starting at the beginning of base. If x is longer than 10 bytes, the memory location after base will be overridden!!
The correct approach would be not to use both base and cont, but to use either one and re-write Strcpy() accordingly -- for short strings it uses base, for longer ones cont. (Try it!) Though using just either one is less "memory efficient" than using both in conjunction, however the clarity and simplification of the code gained will more than make up for the difference.

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