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_worldNote 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:
gcc -v
command that you ran on CSE lab machines; it should start with
gcc version 11....
on the CSE lab machines.ack(0, n)
.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 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 cleanIf 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-finalOnce 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.