Spring 2001, CSE 428: Assignment 3


Distributed: Feb 19.
Due: Mar 1 in class.
Total maximum score: 100 points.

The purpose of this assignment is to provide experience with memory management, and also with the implementation of the data structure "stack". We have noted that in previous assignment several students used a double linked list to implement the environment, while a simple linked list would have been sufficient. The first exercise of this assignment is about two alternative definitions of stack using simple lists. The environment in previous assignment could have been implemented in the same way. (The function lookup of previous assignment is very similar to the function "position" in this assignment.)


  1. [Points 50] Click here (simple version without memory leak tests, maybe easier to understand or enriched version with memory leak tests) to download the partial code of two alternative implementations of a stack, stack1 and stack2. The exercise consists in completing the implementations by providing the definitions of the missing methods, which are:
       stack1::~stack1();  //destructor: it should delete all the elements of the stack, thus avoiding memory leaks
       void stack1::pop();  //it should eliminate the element on top and avoid memory leaks
       int stack1::position(int); //see the code for the description of this function
    
       void stack2::pop(); //it should eliminate the element on top and avoid memory leaks
       int stack2::position(int); //see the code for the description of this function
    
    All the other methods relevant for this exercise (including the destructor for stack2) are defined in the given code. Please make sure that your methods (in particular, pop() and the destructor of stack1) don't leave memory leaks, namely garbage. Also, please make sure that they do not produce dangling references.

    Testing the solution

    Click here to dowload the enriched version of the code for testing purposes. Save it with name "A3_code_stack.C". This version contains some auxiliary base classes with counter fields to keep trace of the number of allocated objects of class element, stack1 and stack2. They are used to check for memory leaks at the end of the function main() . With respect to the simplified version, the enriched version also contains some additional print instruction to help you to follow better what's going on.

    Download this solution frame and fill it in with your definition. Save it with name XXXX.C, where XXXX are the last 4 digits of your student id. Compile XXXX.C with the Unix GNU C++ compiler g++, i.e. give the Unix command

       g++ XXXX.C
    
    Note that XXXX.C contains an instruction to include the file A3_code_stack.C (which should be saved in the same directory). Hence it will include our function main() and the rest of the stacks definitions.

    Now run the compiled code by giving the command

       a.out
    
    If your definitions are correct, you should get the following output:
       Stack1 created. Pushing the numbers 5, 5, 6 and 7 
       Testing the presence of number 5 
       5 is in position 3
       Popping one element from the stack1 
       Testing the presence of number 5 
       5 is in position 2
    
       Stack2 created. Pushing the numbers 5, 6 and 6 
       Testing the presence of number 6 
       6 is in position 1
       Popping an element from the stack2 
       Pushing the numbers 7, 8 and 9 
       Testing the presence of number 6 
       6 is in position 4
    
       Testing the presence of memory leaks 
       element count: 0
       stack1  count: 0
       stack2  count: 0
       No memory leaks. Great! 
    
    If this happens, then you can be reasonably confident that your program is correct. Please keep it in mind however that we will run your solution under a different main() function (with additional test cases) to make sure that your solution is correct in general, not just with the test cases illustrated above.

    Please note the following:.

    1. Make sure that your program can be compiled with g++ and executed. Solutions which cannot be compiled or executed will receive, at most, 20 points (for this exercise).
    2. Don't change the code of A3_code_stack.C !!!. Solutions which work only for your own definition of A3_code_stack.C will receive, at most, 20 points (for this exercise).
    3. Its your responsibility to write a sound, reliable program, so please test your code thoroughly before you submit it.
    4. The TA will test your program with some additional operations (including pop on the last element of the stack and searching for a non existing element). If your program works for the A3_code_stack.C given above, but does not work for some of the additional operations, it will receive between 45 and 35 points (for this exercise), depending of course on how many additional operations give the correct result.

    Format of the solution

    Please give an hard copy of the source code to the instructor by the due date (together with the solution of the other exercises of this assignment). Furthermore, you should also email your definitions to cg428@cse.psu.edu by the due date, so to allow us to check that they run correctly. Please write the code in a single file, send it as an attachment (not by "cut-and-paste"), and use the name XXXX.C, where XXXX are the last 4 digits of your student id, as the filename (example: if the last digits of your id are 1001, then the file should have name 1001.C).


  2. [Points 20] Consider the following five fragments of code using the definition of stack2 above. For each of them, say whether we have memory leaks and/or dangling references after the call to p() returns. In case of dangling references, please specify whether they are to the heap or to the stack (here "stack" stands of course for the machine stack, not for the objects of class stack1 or stack2).
    Note: In the case of Exercise 2.5, the question about ML and DR refers to the point after the completion of the instruction cout << p()->position(2);
    Remember that: A DR is a pointer to a location which is considered free (for further allocation). A ML is a location which is not considered free, and it is not accessible anymore from the program (i.e. it can't be accessed by following chains of links starting from global or local variables).

    1.    void p(){ stack2* s = new stack2(); s->push(2); cout << s->position(2); }
         
         void main() { ... p(); ...}
      

    2.    stack2* s = new stack2(); // global variable
       
         void p(){ stack2* t = s; t->push(2); cout << s->position(2); delete t; }
         
         void main() { p(); ...}
      

    3.    stack2* s = NULL; // global variable
      
         void p(){ stack2 t; t.push(2); s = &t; }
         
         void main() { p(); ...}
      

    4.    stack2* p(){ stack2* t = new stack2(); t->push(2); return t; }
         
         void main() { stack2* t; t = p(); ...}
      

    5.    stack2* p(){ stack2* t = new stack2(); t->push(2); return t; }
         
         void main() { cout << p()->position(2); ...}
      

  3. [Points 30] Click here to download the code of an implementation of a binary tree in C++. The exercise consists in producing a drawing which illustrates the situation in memory (stack and heap) at the moment in which the instruction cout << "level 0 reached \n"; is executed for the first time. Please make explicit all the informations stored in the activation records and in the (allocated part of the) heap at that moment. Use arrows for pointers. Remember that in C++ there is no static link (there is no need for it since nested procedure declarations are not allowed).
    Note: For simplicity, you can represent in the stack only the activation records of main() and of construct_a_tree(int). You can also omit the control link and the temporaries.