CSE 333 24au Homework 0

Due: Tuesday, Oct 1, 2024 by 10:00 pm.

Summary

For homework #0, you will fetch a source distribution that we have prepared. Next, you will trivially modify a simple hello world C application, use make to compile, and run it to learn the magic code. You will then practice working with our course tools: you will use gdb to explore its execution, run a tool that checks your code for memory leaks, and run a third tool that checks for potential style problems.

As you can probably tell, the real goal of this homework is to make sure that all of the course infrastructure is working for you.

Part A: The Code

Overview
All homeworks will be distributed and collected using your personal CSE 333 GitLab repository. Starter code will be added to your repository by the course staff; when you are done with a homework you will tag your repository to indicate which revision should be graded by the course staff. More information about git and GitLab is given below and in other writeups on the course web site. We will demonstrate and discuss the process in sections during the first week of class.

Clone your GitLab repository
Your personal repository will be named something like cse333-24au-wxyz, where wxyz is your userid. If you have not done so already, change to a directory where you want to store a local copy of your personal CSE 333 repository; this local copy is known as a "clone".

You must clone a git repository -- usually to a Linux machine -- if you want to change to its contents; if you only want to look at its contents, you can browse its files via the CSE GitLab web interface. To clone your personal CSE 333 repository, go to its GitLab web interface and look for a "clone" button in the top-right corner; clicking on it and will yield a string labeled "ssl". Copy the long string that starts with git@gitlab... so that you can use it in CSE 333 GitLab Guide.

Follow the instructions in the CSE 333 GitLab Guide to clone your CSE 333 repository; this guide is also linked from the CSE 333 resources page, where there are additional links to the other git resources.

Once you have cloned your repository and completed the CSE 333 GitLab Guide, run the ls -aF command in your local cse333-24au-wxyz directory. You should see something like this:

bash% git clone git@gitlab.cs.washington.edu:cse333-24au-students/cse333-24au-wxyz.git
-- git output appears here
bash% cd cse333-24au-wxyz
bash% ls -aF
.gitignore cpplint.py exercises/ hw0/
   

The .gitignore file lists file types that should not normally be saved in the repository. These are typically things like editor backup files (names ending in ~) and binary object code files (ending in .o). They are files that are generated and used locally while you are working but are recreated as needed from files that are in the repository rather than archived permanently.

We will discuss cpplint.py later in this document.

The exercises directory is empty. It is a place where you can store your code for cse333 exercises, but it is NOT where you should submit your code for grading. We find it useful for sharing exercise code with a TA during online office hours.

If you originally cloned your repository before the staff added the hw0 directory to it, enter a git pull command to bring your local copy up to date. Once you see the hw0 directory, enter cd hw0 to change into that directory to work on the assignment.

Part B: Edit, Compile, and Run hello_world

In the hw0 directory, type make. This command will use the instructions in the file Makefile to compile the hello_world application. Run hello_world by typing the command ./hello_world. You should see one line of output that looks like:

bash% ./hello_world
The magic code is: <xxxxx>
bash%
    
for some value of <xxxxx>. Now, edit hello_world.c using your favorite editor, and change the call to printf() so that it instead says:
bash% ./hello_world
The magic word is: <xxxxx>
bash%
    
Execute make to rebuild, and then re-run hello_world to ensure it outputs the new string.

Part C: Experience the gdb Debugger

Run Our Debugging Script
You're unlikely to have any runtime bugs in this homework, but let's use GDB so that you know what it is capable of. Here is a session that launches the debugger, sets a breakpoint on source line 41 of hello_world.c, prints the values of a couple of variables and an expression, prints a "backtrace" of the stack (ie, shows the sequence of procedure calls that led to executing line 41 of hello_world.c), and then continues execution. You should type the italicized lines. (Note: you may see some differences in gdb or Linux version numbers, or exact addresses of variables and code, but the values should remain the same)

bash$ gdb ./hello_world
GNU gdb (GDB) Red Hat Enterprise Linux 10.2-10.el9
Copyright (C) 2021 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
...
Reading symbols ./hello_world...
(gdb) break 41
Breakpoint 1 at 0x401143: file hello_world.c, line 41.
(gdb) run
Starting program: /home/auser/cse333/hw0/hello_world

Breakpoint 1, main (argc=1, argv=0x7fffffffd668) at hello_world.c:41
41  printf("The magic word is: %X\n", a + b);
(gdb) print argv[0]
$1 = 0x7fffffffe394 "/home/auser/cse333/hw0/hello_world"
(gdb) print a
$2 = -889262067
(gdb) print /x a
$3 = 0xcafef00d
(gdb) print a+b
$4 = -559038737
(gdb) backtrace
#0  main (argc=1, argv=0x7fffffffd668) at hello_world.c:41
(gdb) continue
Continuing.
The magic word is: <xxxxx>
[Inferior 1 (process 6760) exited normally]
(gdb) quit
bash$
    

For gdb to be useful, you must use gcc's -g option during compilation; the Makefile we distributed does that. Most gdb commands can be abbreviated; for example, you can use p instead of print and bt instead of backtrace. The full versions of commands are used in the above example for clarity, but you will quickly want to learn the abbreviations.

Debug Some Sample Code
Lastly, let's examine the commented-out function call at line 42. Suppose there is a bug in this 2-ary recursive function's base case, and you want to find the maximum depth of the callstack for any invocation where the first argument is 0 (ie, the depth of the deepest backtrace for any call to ack(0, n)). How might you determine this maximum depth? What gdb commands might you run? Since you may or may not need more than one comamnd, we strongly recommend looking at a reference card of all gdb commands.

Part D: Verify You Have No Leaks

Throughout the quarter, we'll be testing whether your code has memory errors, such as leaks or reading values from uninitialized variables. We'll be using Valgrind to do this. Try out Valgrind for yourself:

bash% valgrind --leak-check=full ./hello_world
    
Note that Valgrind prints out that no memory leaks were found in our starter code

Part E: Check for Common Bugs and Style Issues

Another requirement during the quarter is that your code must be written legibly and follow widely-understood safe coding practices; in this course we will follow Google's C++ Style Guide to do this. Many (but not all!) of its recommendations can be automatically verified using the cpplint.py Python script that was pushed to your GitLab repository. Try it yourself:

bash% ../cpplint.py --clint hello_world.c
    

(The --clint option tells cpplint that the source file contains C code. If this option is omitted, cpplint assumes the file contains C++ code.)

Unless explicitly specified, any code that you submit for grading must pass cpplint.py; in fact, you may find that our starter code has an error that you ought to resolve! Although the specific lint error in our starter code is quite nitpicky, you should generally try to clean up all lint errors; linters detect known-bad coding patterns, so you should have very good reasons to ignore its output (such as explicit instructions from your course staff).

Part F: Document Your Work

Create a README.md file in the hw0 directory that contains:

We are not picky about the format of this file as long as it has the above information. Be sure to git add this file and push it to your gitlab repository.

Homework Submission and Grading

Once you're done (yay!), "turning in" the assignment is logically simple: create a tag in your git repository to designate the revision (ie, commit) that the course staff should examine for grading. HOWEVER! there are multiple ways to get "logically simple" task this wrong; for hw0, there's always at least 1 person -- and sometimes as many as 5% of the enrolled students -- who doesn't follow these instructions in the following order and gets a 0 grade.

The general idea for turning in your homework is:

  1. Tidy up your code, then ensure that everything is properly committed and pushed to your repository.
  2. Add a tag to your repository, which designates a specific commit hash as your finished assignment.
  3. Create a fresh clone of your respository to verify everything has been done properly.

1. Tidy up and push to your repository
Commit all of your changes to your local clone, then push them to your (remote) repository. If you need a refresher on how to do this, see the CSE GitLab Guide. To verify that your push was successful, run the following commands in your hw0 directory:

bash% make clean
bash% git pull
bash$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean
    
If you see messages about uncommitted changes or any other indications that the latest version of your code has not been pushed to your GitLab repository, fix those problems before proceeding. You should re-run the above commands to ensure the problems have been fixed.

We cannot state this strongly enough: DO NOT TAG your repository for grading until after you have pushed and verified your repository in this step.

2. Tag your repository
Recall that a git repository's state is described by its commits, not by a timestamp; so you would say "my team pushed to production at aabbcc" instead of "my team pushed to production at 10:00am on Monday. To indicate that the most recent commit is the version of your repo that you want graded, you will tag that commit with the special string hw0-final and then push that new tag to your repository. Your tag must be pushed to your repository; it cannot be left in your local clone, because the course staff doesn't have access to your clone.

bash% git tag hw0-final
bash% git push --tags
    

3. Verify the tag in a fresh clone
To ensure that your tag is correct, create a brand new, empty directory that is nowhere near your previous clone. It is really, really, REALLY important that this new directory not be nested inside your regular working directory. Next, clone your repository into that new location:

bash% cd <somewhere-completely-different>
bash% git clone git@gitlab.cs.washington.edu:cse333-24au-students/cse333-24au-wxyz.git
bash% cd cse333-24su-wxyz
bash% git checkout hw0-final
    
(Use your own userid instead of wxyz, of course.)

In the above commands, the commands after git clone will cause git to switch to the tagged commit that you created in step 2, above. In fact, we run that same command when we grade your files.

At this point you should see your hw0 directory. cd into it, run make, and run any tests or verifications you wish. If there are any problems, immediately delete this new clone (ie, rm -rf <somewhere-completely-different>/cse333-24au-wxyz), go back to your regular working clone, and fix whatever is wrong. A frequent bug is forgetting to git push --tags.

If you need to do more than just pushing the tag, the next step is to delete your original hw0-final tag; this must be done before attempting any repairs to your repository. To delete the tag, go into your regular working clone and run:

bash% git tag -d hw0-final
bash% git push origin :refs/tags/hw0-final
    
Once the tag has been deleted, perform your repairs (remembering to push your repairs to your repo!), and restart from step 2.

For hw0, we'll give you full credit if you learn the magic code, made the requested change, and answered the above questions.