Project 0: Program Trace Verifier
Due Friday, 2019/01/18, 11:59:59PM
After that, get started on the project immediately! Here is the upload site. Make sure that you can log in to the upload site.
The goals of this project are to:
- brush up on your C++,
- use the stack data structure, which you are familiar with,
- use the STL (Standard Template Library) stack, string, and iostream classes,
- test your program in the command line environment with input/output redirection and diff utilities, and
- get used to how this course uses the upload site.
When a compiled C++ program executes, it usually starts in the function called
main. From there, it can call another function,
read_input, which in turn might call another function, such
istream::operator>>, etc. Each called function takes the next slot
(or `frame') on the program's call stack. The currently-executing
function is on the top of that stack.
The executing program also returns from each called function, in the reverse
order from the call order. So continuing our example, it must first return from
istream::operator>>, then return from
read_input, then return
main. Conversely, it could not return from
before it had returned from the inner call to
There are many program analysis tools that allow programmers to examine the behavior of executing programs. You're probably familiar with debuggers, which allow a programmer to pause an executing program, examine variables, etc. The program Valgrind (pronounced "val-grinned") examines executing programs for various problems like memory leaks. Many such tools can operate on or produce program traces, which describe things like the order of function calls and returns. We expect traces to be valid, in that every function call has an appropriately matched return from that function.
Here are examples of valid and invalid program traces. We'll assume that
we are starting in the (unnamed) outermost function (e.g.
|Trace 1 (valid)||Trace 2 (invalid)||Trace 3 (invalid)||Trace 4 (invalid)|
call read_input call istream::operator>> return istream::operator>> call istream::operator>> return istream::operator>> return read_input call solve call log return log call abs return abs call ostream::operator<< return ostream::operator<< return solve
call read_input call istream::operator>> return istream::operator>> call istream::operator>> return read_input call solve call log return log call abs return abs call ostream::operator<< return ostream::operator<< return solve
call read_input call istream::operator>> return istream::operator>> call istream::operator>> return istream::operator>> return read_input call log return log call abs return abs call ostream::operator<< return ostream::operator<< return solve
call read_input call istream::operator>> return istream::operator>> call istream::operator>> return istream::operator>> return read_input call solve call log return log call abs return abs call ostream::operator<< return ostream::operator<<
Trace 1 is valid, because every function call return in the correct order. Traces 2-4 are invalid, because:
- Trace 2 returns from
read_inputbefore it returns from
- Trace 3 returns from
solve, but no functions are currently being called.
- Trace 4 does not return from
Your task for this project is to determine the validity of program traces. You'll be given a trace of an executing program, and you should determine whether the trace is valid or not. If it's not valid, your program should describe why.
Use an STL stack to keep track of called functions. Here is a good algorithm for validating program traces:
- For each function called, place the function's name on the stack.
- When a function returns, check that its name matches the name on the top of the stack.
- Finally, at the end of the trace, check that the stack is empty.
Your program should read from standard input (i.e. cin). It should write to standard output (i.e. cout). This is the way we construct ALL of our projects, unless otherwise indicated.
Each input consists of one trace, containing between 0 and 10,000 lines.
Input ends at end-of-file.
Each line starts with either the word
return, followed by
a single space, followed by a function name. The function name contains 1 to
30 characters, consisting only of letters (a-z), digits (0-9) and some
punctuation (underscore, period, colon, less than, and greater than). If the
line starts with
call, that indicates a called function; while
return indicates a function that is returning.
If the program call trace is valid, output two things: "
Valid trace" and
Maximum call depth was DEPTH", where
DEPTH is the maximum size of
the call stack at any time during the program's execution.
If the program call trace is not valid, then stop processing it as soon as the
first error is encountered. Print out "
Invalid trace at line LINENUMBER",
LINENUMBER is the line of input (starting at 1) where the error
is earliest detected. After this, specify the type of error (filling in
appropriate names for
Returning from FUNCTION1 instead of FUNCTION2" — If the trace tries to return from
FUNCTION2but the matching function should have been
Returning from FUNCTION1 but no functions are currently being called" — If the trace tries to return from
FUNCTION1but there are no functions currently being called.
Not all functions returned" — If the trace ends but not all functions have returned.
Stack trace" and then the names of the functions on the call stack (from top of the stack to bottom) when the error occurred, one line per name.
Use the sample executables to see real examples of how the output should be formatted.
You should use the .cpp file provided here, modify it appropriately, and upload your solution. You may modify anything you like, but it has a basic structure you can follow.
Here are sample executables for you which correctly solve this problem. When you design test cases, you can judge your output against the output from the correct solution. Here is a correct solution in various compiled formats:
For each of these, you need to run them from the command-line (i.e. DOS or bash
or Terminal.app). You can't just download them and double-click them to run.
Also, for the linux and OSX binaries, after you've downloaded them you need to
make sure that they are executable. To do this, from the command line type
chmod +x file, where
file is the name of the program
If you give a command-line argument to these executables, they will print extra information about how it is processing the input. For example, this will execute the program like normal, redirecting input from a file called my_input.txt:
% project0_solution_dos.exe < my_input.txt
But here is the mode of operation that will cause the program to print out what it is doing in more detail:
% project0_solution_dos.exe printMore < my_input.txtThe command-line argument doesn't have to be the word "printMore", it can be anything.
Sample input files
Use these sample input files to compare the output of your solution to the correct output. You can get the correct output by running the input through one of the sample executables. You should download these input files to your computer (in other words, don't copy and paste), and use file redirection to redirect the inputs into the sample executable and into your program. You should also use file redirection to capture the outputs from these programs. Don't use copy/paste, and don't type things directly into your program. Please read this for a more complete description of how to test your program, and how to use file redirection..
Please note that you may see the wrong thing if you view these input files in your web browser — it may interpret the text as HTML, when it should show you plain text. Instead, you should download them directly to your computer (e.g. right-click on each link and select the appropriate download option). In general, you should AVOID copy-and-pasting input and output in this class.
These are not the only inputs your program must solve; they are merely examples. The upload site will have more tests, to which you do not have access. Therefore, making your own tests is essential.
Remember when writing this program to adhere to the coding style guidelines. This is an individual project, so you must work alone. No credit will be given for a solution which does not pass the online judging system. For more detailed instructions, read the project submission guidelines.