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