Lab 1: C programming under Unix

Lab sessions Mon Jan 16 to Thu Jan 19

Lab written by Julie Zelenski

During lab, you will experiment and explore, ask and answer questions, and get hands-on practice in a supported environment. The lab exercises revisit topics from recent lectures/readings and prepare you to succeed at the upcoming assignment. To record lab participation, we use an online checkoff form that you fill out as you work. Lab is not a race to answer exactly and only the checkoff sheet-- these questions are deliberately trivial and we use them merely to record attendance and get a read on how far you got. Instead of using the checkoff questions to dictate your activity, let satisfying your curiosity and achieving a sense of mastery be your guide. The combination of active exploration, give and take with your peers, and the guidance of the TA makes lab time truly special. Your sincere participation can really accelerate your learning!

Learning goals

During this lab you will:

  1. get further practice with common unix utilities
  2. work through editing, compiling, testing, and debugging C programs in the unix environment

Find an open computer to share with a partner and introduce yourselves. Together the two of you will tackle the exercises below. Everyone is encouraged to discuss issues and share insights with all your labmates. The TA will circulate to offer advice and answers and keep everyone progressing smoothly.

Get started

We distribute all labs and assignments as Mercurial repositories. If you haven't yet, read the CS107 mercurial guide and be sure both partners have set up their Mercurial environment. Clone the lab repo by using the command below. This command creates a lab1 directory containing the source files and Makefile.

hg clone /afs/ir/class/cs107/repos/lab1/shared lab1

Pull up the online lab checkoff right now and have it open in a browser so you can jot things down as you go. Only one checkoff needs to submitted for both you and your partner.

Lab exercises

Part 1: Unix practice

This warmup exercise is to try out the unix commands suggested below while simultaneously chatting up your labmates about your assign0 experiences. How is everyone doing so far on getting comfortable in the unix environment? Do you have open questions or an issue you'd like help with? Did you learn a nifty trick or two that you'd like share? Let's hear it!

Part 2: Implement and test myprintenv

Review, edit, and build the code

The myprintenv.c file is a partial implementation of a printenv-like program. The given code correctly handles printing the list of all environment variables, but is missing the handling for when invoked with an argument. Pull up the printenv man page to review how it supposed to handle it and then edit myprintenv.c to implement that behavior. Use make to build the program.

Test manually

Once your code successfully builds, it's time to test! One simple means to verify correctness is by comparing your results to a known-correct solution. For example, runprintenv PATH then run myprintenv PATH and manually eyeball the outputs to confirm they match. Even better would be to capture those outputs and feed them to diff so the tools can do the work. To make testing as painless as possible for you, we've automated simple output-based comparison into a CS107 tool called sanitycheck. You'll use sanitycheck throughout the quarter, so let's get some practice using it right away!

Test with sanitycheck

First read our sanitycheck instructions, then try running sanitycheck in your lab1 directory. Follow along by reading the report sanitycheck produces while running. A test case will run a myprintenv command, compare its output to the solution, and report if mismatched. The default sanitycheck for lab1 runs four test cases on myprintenv. How did your implementation fare on them? If you passed all four, great for you! It not, review the sanitycheck report to learn which one(s) you didn't pass. Follow up with some manual testing until you fully understand the problem, edit your code to resolve it, and build and test again. Repeat until your version passes all the sanity tests for myprintenv.

Part 3: Test and debug mywc

The mywc.c file implements a wc-like program (man wc) that is intended to count the lines, words, and characters from a file and report the longest line. The code was written by your colleague who claimed it is "complete", but on his way out the door he mutters something unintelligible about possible unfixed bugs. Uh oh... Your task is to test and debug the program into a fully functional state using CS107 sanitycheck and the gdb debugger. Take a moment to skim the CS107 guide to gdb before going further.

Part 4: Give valgrind a whirl

Although your programs aren't yet making heavy use of memory/pointers, they will soon and a skill you want to add to your arsenal is using Valgrind for its help detecting memory errors. If you haven't already, review our guide to valgrind and let's try out Valgrind now.

Becoming a skilled user of Valgrind is invaluable to a programmer. We recommend that you run Valgrind early and often during your development cycle. It's best to focus on one memory problem at a time. Your strategy should go something like this:

Repeat for any remaining errors. Don't move on until you get a clean report from Valgrind. Note that memory leaks don't demand the immediate attention that errors do. Leaks can (and should) be safely ignored until the final phase of polishing a working program.

Check off with TA

At the end of the lab period, submit the checkoff form and ask your lab TA to approve your submission so you are properly credited for your work. It's okay if you don't completely finish all of the exercises during lab; your sincere participation for the full lab period is sufficient for credit. However, we highly encourage you to work through any unattempted parts or unresolved issues to solidify your knowledge of this material before moving on! Try our self-check to reflect on what you got what from this lab and whether you're feeling ready for what comes next!

Contents