Lab 5 - Copy Constructors and Assignment Operators

The purpose of this lab is to see why copy constructors and assignment operators are vital for class which have dynamic array member variables.

Copy the class list.cpp to your directory using wget or copy/paste (see Labs 1 and 2 for these commands). This is a class which has a dynamic double array, but does not have a copy constructor or assignment operator defined. Because of this, any time the copy constructor or assignment operator would be needed, the default action of copying the base address of the array over occurs, so multiple objects point to the same array.

Compile and run the program as given using the following commands:

g++ -g -o lab5 list.cpp
./lab5
Your output should appear similar to the following (without the color coding, which I've added to facilitate the discussion below, also your addresses may differ from the addresses given):
Report and value of a (empty list):
array pointer address=0x0 count=0 cap=0


Report and value of b (10 values from array 1):
array pointer address=0xea7010 count=10 cap=10
4.5 6.5 2.3 1.2 6.2 9.8 12.3 4.2 11.1 9.4

Report and value of c (6 values from array 2):
array pointer address=0xea7050 count=6 cap=6
5.2 4.3 7.1 8.5 3.7 2.8

Report and value for the clone of c (copy constructor):
array pointer address=0xea7050 count=6 cap=6
5.2 4.3 7.1 8.5 3.7 2.8

Report and value of a after using a = c (assignment operator):
array pointer address=0xea7050 count=6 cap=6
5.2 4.3 7.1 8.5 3.7 2.8

Report and value of a after using a = b (assignment operator):
array pointer address=0xea7010 count=10 cap=10
4.5 6.5 2.3 1.2 6.2 9.8 12.3 4.2 11.1 9.4
*** glibc detected *** ./lab5: double free or corruption (fasttop): 0x0000000000ea7050 ***
======= Backtrace: =========
/lib/libc.so.6(+0x71ad6)[0x7fd374169ad6]
/lib/libc.so.6(cfree+0x6c)[0x7fd37416e84c]
./a.out[0x400fd9]
./a.out[0x4013b9]
/lib/libc.so.6(__libc_start_main+0xfd)[0x7fd374116c4d]
./a.out[0x400be9]
======= Memory map: ========
00400000-00402000 r-xp 00000000 fe:02 435135                             /home/fac/melissa/cs222/lab5
00601000-00602000 rw-p 00001000 fe:02 435135                             /home/fac/melissa/cs222/lab5
00ea7000-00ec8000 rw-p 00000000 00:00 0                                  [heap]
7fd370000000-7fd370021000 rw-p 00000000 00:00 0 
7fd370021000-7fd374000000 ---p 00000000 00:00 0 
7fd3740f8000-7fd374250000 r-xp 00000000 fe:00 54682                      /lib/libc-2.11.2.so
7fd374250000-7fd37444f000 ---p 00158000 fe:00 54682                      /lib/libc-2.11.2.so
7fd37444f000-7fd374453000 r--p 00157000 fe:00 54682                      /lib/libc-2.11.2.so
7fd374453000-7fd374454000 rw-p 0015b000 fe:00 54682                      /lib/libc-2.11.2.so
7fd374454000-7fd374459000 rw-p 00000000 00:00 0 
7fd374459000-7fd37446f000 r-xp 00000000 fe:00 54654                      /lib/libgcc_s.so.1
7fd37446f000-7fd37466e000 ---p 00016000 fe:00 54654                      /lib/libgcc_s.so.1
7fd37466e000-7fd37466f000 rw-p 00015000 fe:00 54654                      /lib/libgcc_s.so.1
7fd37466f000-7fd3746ef000 r-xp 00000000 fe:00 42525                      /lib/libm-2.11.2.so
7fd3746ef000-7fd3748ef000 ---p 00080000 fe:00 42525                      /lib/libm-2.11.2.so
7fd3748ef000-7fd3748f0000 r--p 00080000 fe:00 42525                      /lib/libm-2.11.2.so
7fd3748f0000-7fd3748f1000 rw-p 00081000 fe:00 42525                      /lib/libm-2.11.2.so
7fd3748f1000-7fd3749e7000 r-xp 00000000 fe:07 573470                     /usr/lib/libstdc++.so.6.0.13
7fd3749e7000-7fd374be7000 ---p 000f6000 fe:07 573470                     /usr/lib/libstdc++.so.6.0.13
7fd374be7000-7fd374bee000 r--p 000f6000 fe:07 573470                     /usr/lib/libstdc++.so.6.0.13
7fd374bee000-7fd374bf0000 rw-p 000fd000 fe:07 573470                     /usr/lib/libstdc++.so.6.0.13
7fd374bf0000-7fd374c05000 rw-p 00000000 00:00 0 
7fd374c05000-7fd374c23000 r-xp 00000000 fe:00 42528                      /lib/ld-2.11.2.so
7fd374e0a000-7fd374e0e000 rw-p 00000000 00:00 0 
7fd374e1f000-7fd374e22000 rw-p 00000000 00:00 0 
7fd374e22000-7fd374e23000 r--p 0001d000 fe:00 42528                      /lib/ld-2.11.2.so
7fd374e23000-7fd374e24000 rw-p 0001e000 fe:00 42528                      /lib/ld-2.11.2.so
7fd374e24000-7fd374e25000 rw-p 00000000 00:00 0 
7fff77b21000-7fff77b36000 rw-p 00000000 00:00 0                          [stack]
7fff77bff000-7fff77c00000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted
Note the addresses in red and blue are the same, even though they are outputing separate objects. This is because the copy constructor and assignment operator are not defined, so the base address of c was just copied over to a and clone, rather than allocating new arrays for a and clone. Likewise, the base address of b was copied over when a = b was called.

Finally, note the long block of text that appears at the end of the program. When main() ends, all the objects created in main (a, b, c and clone) are destroyed. Since a and b point to the same array and c and clone point to the same array, you will end up trying to call delete [] array on the same memory address more than once. When this happens, the system aborts your code with this error message about "double free" (free is the C version of delete). This is another indication that the copy constructor and assignment operators have not properly been defined.

Assignment

Download the corrected code list_fixed.cpp using wget or copy/paste. The copy constructor and assignment operator have been added to this code to fix the issue of two or more objects pointing to the same memory address when using dynamic arrays.

Compile and run the code using

g++ -o lab5fixed list_fixed.cpp
./lab5fixed
Note that the memory addresses for the clone of c and a after each assignment are now different than the original objects b and c.

Answer the following questions in the Moodle text box for this assignment:

  1. What is the output you get after running lab5fixed? (Copy and paste the output into the Moodle text box)
  2. Look at the code for list_fixed.cpp. Why does the assignment operator have to check that the source object is different than the current object but the copy constructor does not? (Hint: think about WHEN each of these functions can be called in the lifetime of an object)
  3. Similarly to Question 2, why does the assignment operator have to delete its existing array before allocating a new one if the source object has a larger array? (Hint: What would happen if it didn't delete the existing array before allocating a new one?)