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.
For the first activity, we will revisit our old friend gcd.
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:
gcd.c
: This contains a straightforward implementation of the gcd
algorithm.
main.c
: This is a driver program that utilizes the gcd
implementation.
Makefile
: This a skeleton of the Makefile
you will need to complete
for this activity.
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:
libgcd.a
: This is a static library that depends on gcd.o
.
libgcd.so
: This is a shared library that depends on gcd.o
.
gcd-static
: This is a static executable that depends on main.o
and
libgcd.a
gcd-dynamic
: This is a dyanmic executable that depends on main.o
and libgcd.so
all
: This is the default rule and should build all four
TARGETS
above.
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
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 ...
Answer the following questions in your README.md
:
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
What libraries does gcd-static
depend on? What libraries does
gcd-dynamic
depend on? How did you find out?
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?
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.
The hints may spoil the surprises in the activity, so only view them when you are stuck: Toggle Hints.
You should use CC
and CFLAGS
when compiling objects, but LD
and
LDFLAGS
for linking executables. AR
and ARFLAGS
are used for
static libraries.
Static executables depend on static libraries and dynamic executables depend on shared libraries.
In regards to automatic variables, with a rule, $@
refers to the target
to produce, $<
refers to the first source, $^
refers to all the
sources.
rpath can be used to save link time information such as the location of a library.
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!
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.
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:
is_palindrome.c
: This an implementation of a program that checks whether
or not each line read from stdin
is a [palindrome].
is_palindrome.input
: This is sample input that should be redirected into
the is_palindrome
program.
is_palindrome.output
: This is a sample output of what the
is_palindrome
program should print out given the is_palindrome.input
.
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:
all
: This is the default target and builds the is_palindrome
target.
is_palindrome
: This builds the is_palindrome
program from the
is_palindrome.c
source file.
clean
: This removes the is_palindrome
program and any intermediate object files.
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
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:
Segmentation Fault: There is an invalid memory access that causes the program to crash.
Invalid Memory Access: There are invalid memory accesses that do not cause the program to crash.
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:
It compiles without warnings or errors.
It executes without errors.
It produces the output in is_palindrome.output
given the input from
is_palindrome.input
.
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.
Answer the following questions in your README.md
file:
How did you download and extract the is_palindrome.tar.gz archive? What commands did you use?
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.
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.
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.
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
The hints may spoil the surprises in the activity, so only view them when you are stuck: Toggle Hints.
You can use tar to extract the archive.
One of the bugs has to do with static memory allocation and string literals.
One of the bugs can be fixed by using the strdup function.
One of the bugs can be fixed by using the free function.
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 ....
This activity requires that you work on the student machines or have access to AFS on your Unix machine.
The hints may spoil the surprises in the activity, so only view them when you are stuck: Toggle Hints.
Because you don't have access to the source code of the program, you will
have to rely on tools such as strings and strace to inspect the
behavior of the COURIER
.
You can either use grep to filter the output of strace or you can use
the -e
flag with strace to limit the output of strace to particular
system calls.
You can lookup system calls by doing man 2 SYSCALL
. For instance:
$ man 2 open
For the COURIER
, you will want to look closely at stat, open, and
read.
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:
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
.
If you have any questions, comments, or concerns regarding the course, please
provide your feedback at the end of your README.md
.
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.
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!).