The goal of the third homework assignment is to allow you to practice with basic Unix developer tools for the C/C++ programming languages.

For this assignment, record your responses to the following activities in the README.md file in the homework03 folder of your assignments Bitbucket repository and push your work by 11:59 PM Friday, February 5, 2016.

Activity 01: Make It (5 Points)

For the first activity, we will revisit our old friend gcd.

Task 0: Download and Extract

To start the activity you must first download and extract the gcd.tar.gz archive to the homework03 directory of your assignments repository. This archive should contain the following files:

  1. gcd.c: This contains a straightforward implementation of the gcd algorithm.

  2. main.c: This is a driver program that utilizes the gcd implementation.

  3. Makefile: This a skeleton of the Makefile you will need to complete for this activity.

Task 1: Complete Makefile

Once you have the files, your should take a look at the contents of each. In particular, your Makefile should look like this:

CC=       gcc
CFLAGS=   # TODO
LD=       gcc
LDFLAGS=  # TODO
AR=       ar
ARFLAGS=  # TODO
TARGETS=  # TODO

all:  $(TARGETS)

# TODO

clean:
          # TODO

You are to complete this Makefile so that you have the following rules:

  1. libgcd.a: This is a static library that depends on gcd.o.

  2. libgcd.so: This is a shared library that depends on gcd.o.

  3. gcd-static: This is a static executable that depends on main.o and libgcd.a

  4. gcd-dynamic: This is a dyanmic executable that depends on main.o and libgcd.so

  5. all: This is the default rule and should build all four TARGETS above.

  6. clean: This should remove all the TARGETS and any intermediate objects.

For the intermediate object files (ie. main.o, gcd.o), you should use pattern rules. Moreover, the rules should use automatic variables whenever possible. Furthemore, you should use the variables CC, CFLAGS, LD, LDFLAGS, AR, and ARFLAGS in your recipes.

Once you have a working Makefile, you should be able to do the following:

$ make # Build all targets

$ ./gcd-static 12 25  # Execute static version
gcd(12, 25) = 1

$ ./gcd-static 12 28  # Execute static version
gcd(12, 28) = 4

$ make clean # Remove all targets and intermediate objects

Debugging Symbols

If you are using the student machines and you are using the gcc version in ~csesoft then you need to add -gdwarf-2 to your CFLAGS to get intelligent debugging symbols:

$ gcc -g -gdwarf-2 ...

Task 2: Questions

Answer the following questions in your README.md:

  1. Given the following pairs of files, identify which one of the two is larger and discuss why:

    a. libgcd.a vs libgcd.so

    b. gcd-static vs gcd-dynamic

  2. What libraries does gcd-static depend on? What libraries does gcd-dynamic depend on? How did you find out?

  3. Try to run the gcd-dynamic application. Did it work? Why or why not? Which environment variable could we set to allow gcd-dynamic to execute and what would we set it to?

  4. What are the advantages and disadvantages to static and dynamic linking? If you were to create an application which type of executable would you want to produce by default? Explain your choice and discuss your reasoning.

Hints

The hints may spoil the surprises in the activity, so only view them when you are stuck: Toggle Hints.

Activity 02: Fix It (7 Points)

For the second activity, you are fix the is_palindrome program, which once compiled and fully functioning, should run as follows:

$ ./is_palindrome < is_palindrome.input
abba is a palindrome!
tacocat is a palindrome!
taco cat is a palindrome!
nope is not a palindrome!

Cool Story Bro

This was a classic programming contest and programming interview question. The instructor may or may not have been asked this question by the Redmond Beast.

Task 0: Download and Extract

To start the activity you must first download and extract the is_palindrome.tar.gz archive to the homework03 directory of your assignments repository. This archive should contain the following files:

  1. is_palindrome.c: This an implementation of a program that checks whether or not each line read from stdin is a [palindrome].

  2. is_palindrome.input: This is sample input that should be redirected into the is_palindrome program.

  3. is_palindrome.output: This is a sample output of what the is_palindrome program should print out given the is_palindrome.input.

Task 1: Write Makefile

Once you have the files, you should first create a Makefile to build it. Since you will be debugging the program you want to be sure that the executable includes debugging symbols.

Your Makefile should the following targets:

  1. all: This is the default target and builds the is_palindrome target.

  2. is_palindrome: This builds the is_palindrome program from the is_palindrome.c source file.

  3. clean: This removes the is_palindrome program and any intermediate object files.

  4. test: This uses the diff utility to compare the output of is_palindrome given is_palindrome.input and the contents of the expected output stored in is_palindrome.output. This should depend on all three of the mentioned files.

Once you have the Makefile, you should be able to do the following:

$ make        # Build application

$ make clean  # Remove application and objects

$ make test   # Build nd test the application

Task 2: Fix Bugs

After you have a Makefile and can build the is_palindrome application, you are now ready to fix it! In particular, the given implementation of is_palindrome has three types of memory errors:

  1. Segmentation Fault: There is an invalid memory access that causes the program to crash.

  2. Invalid Memory Access: There are invalid memory accesses that do not cause the program to crash.

  3. Memory Leak: The program does not manage memory properly and loses track of data.

You are to use gdb, valgrind, and whatever other tools you wish to track down these bugs and fix the is_palindrome program. Your program is correct when:

  1. It compiles without warnings or errors.

  2. It executes without errors.

  3. It produces the output in is_palindrome.output given the input from is_palindrome.input.

KISS

The fixes are mostly one-liners (either add, removing, or modifying one line of code). If you are doing much more than that, you are doing it wrong.

Task 3: Questions

Answer the following questions in your README.md file:

  1. How did you download and extract the is_palindrome.tar.gz archive? What commands did you use?

  2. What flags did you use to force gcc to include debugging symbols in the is_palindrome executable? How does including these symbols affect the size of the executable? Explain and provide evidence.

  3. For each of the three classes of bugs, describe how you diagnosed the problem, what the problem was, and how you fixed it. Be sure to explain the commands you used to track down the bugs and why your modifications address the issues you found.

  4. Of the bugs you found and fixed, which one was the hardest? Discuss why that bug was so difficult for you and what can be done in the future to prevent such bugs.

Source Code

You should include your fixed version of is_palindrome for verifcation by adding and commiting the source code and Makefile:

$ cd homework03/is_palindrome # Go to is_palindrome directory

$ git add Makefile is_palindrome.c is_palindrome.input is_palindrome.output # Add source files

$ git commit -m "homework 03: add is_palindrome code" # Commit your work

Hints

The hints may spoil the surprises in the activity, so only view them when you are stuck: Toggle Hints.

Activity 03: Trace It (3 Points)

For the last activity, you are to deliver a package to the ORACLE. Unfortunately, no details about where or what the package should contain has been given. Instead, all you have been told is to go contact the COURIER in the following location:

/afs/nd.edu/user15/pbui/pub/bin/COURIER

Get him talking and hopefully he will give you hints on delivering the dead drop.

As you interact with the COURIER, record what see saw and what commands you executed in your README.md. Be thorough as possible, as we will need this log to reconstruct your mission. Here is an example of what your README.md for this activity should look like:

1. Contacting the `COURIER`:

      $ /afs/nd.edu/user15/pbui/pub/bin/COURIER

  He had the following message:

      ...

2. Finding the package location:

      $ command ...

    To find the location of the package, I ran the command above to ....

Student Machines and AFS

This activity requires that you work on the student machines or have access to AFS on your Unix machine.

Hints

The hints may spoil the surprises in the activity, so only view them when you are stuck: Toggle Hints.

Guru Point (1 Point)

For extra credit, you are to customize your favorite $EDITOR by adding useful programming or development extensions and plugins that will make your Unix programming environment more productive. Here are some sources of inspiration:

Nano

  1. Nano Text Editor and nanorc Tips and Tricks

Vim

  1. Vim as your IDE
  2. Vim: revisited
  3. How to turn Vim into a full-fledged IDE

Emacs

  1. C/C++ Development Environment for Emacs
  2. Mastering Emacs
  3. Org mode

If you come across any other tutorials or resources, please share them on Slack.

To get credit, you must show either a TA or the instructor a demonstration of your tricked out $EDITOR.

Feedback

If you have any questions, comments, or concerns regarding the course, please provide your feedback at the end of your README.md.

Submission

To submit your assignment, please commit your work to the homework03 folder in your assignments Bitbucket repository by 11:59 PM Friday, February 5, 2016.

Source Code Only

Do not commit binary files to your repository. Besides taking unnecessary amounts of space, they are not used by the graders and just make them angry. Only commit source code such as your *.c files or your Makefile. The libraries and executables generated by your code do not go in the repository (the graders can rebuild them as necessary!).