11# C-programming-pre-lab <!-- omit in toc -->
22
3- Pre -lab to get started on compiling and running C programs and using ` valgrind ` to identify
4- memory leaks.
3+ This is a pre -lab to get you started started on compiling and running C programs
4+ and using ` valgrind ` to identify memory leaks.
55
66- [ Background] ( #background )
77 - [ Compiling and running a C program] ( #compiling-and-running-a-c-program )
8+ - [ Compiling and running the tests] ( #compiling-and-running-the-tests )
89 - [ Using valgrind to find memory leaks] ( #using-valgrind-to-find-memory-leaks )
910- [ What to do] ( #what-to-do )
1011
@@ -50,11 +51,11 @@ Assuming you're in the project directory, you can compile
5051this using the command
5152
5253``` bash
53- gcc -g -Wall -o check_whitespace check_whitespace.c
54+ gcc -g -Wall -o check_whitespace main.c check_whitespace.c
5455```
5556
56- ` gcc ` is the GNU C Compiler, which is pretty much the only C compiler
57- people use on Linux boxes these days. The meaning of the flags:
57+ ` gcc ` is the GNU C Compiler, which, along with Clang/LLVM, dominates the
58+ C/C++ compiler space on Linux boxes these days. The meaning of the flags:
5859
5960- ` -g ` tells ` gcc ` to include debugging information in the generated
6061 executable. This is allows, for example, programs like ` valgrind `
@@ -74,13 +75,110 @@ people use on Linux boxes these days. The meaning of the flags:
7475 will write the executable to a file called ` a.out ` for strange
7576 historical reasons.
7677
78+ After the flags, we provide a list of all the ` .c ` files that need to be
79+ compiled and [ linked together] ( https://en.wikipedia.org/wiki/Linker_(computing) )
80+ to form a working executable.
81+
7782Assuming your program compiled correctly (** check the output!** ) then you
7883should be able to run the program like any other executable:
7984
8085``` {bash}
8186./check_whitespace
8287```
8388
89+ ### Compiling and running the tests
90+
91+ This includes an example of using
92+ [ the GoogleTest library] ( https://google.github.io/googletest/ )
93+ for writing unit tests for C and C++ programs. The tests are in
94+ ` check_whitespace_test.cpp ` , which has a ` .cpp ` extension because
95+ tests in GoogleTest are actually C++ (` .cpp ` ) instead of just C.
96+
97+ Below are examples of a few tests in GoogleTests:
98+
99+ ``` c++
100+ TEST (Strip, WhitespaceOnBothEnds) {
101+ ASSERT_STREQ("frog", strip(" frog "));
102+ }
103+
104+ TEST(IsClean, NoWhitespace) {
105+ ASSERT_TRUE(is_clean("University of Minnesota Morris"));
106+ }
107+ ```
108+
109+ The two arguments to `TEST` are arbitrary names. The first is the name of
110+ the _suite_ this test is part of; we just used the name of the function
111+ being tested by this test (`Strip` or `IsClean`). The second is the name
112+ of this particular test, and should hopefully provide some useful information
113+ on what's being tested here.
114+
115+ GoogleTest has quite a few assertions. Here we're using `ASSERT_STREQ`, which
116+ asserts that two strings (`STR`) are equal (`EQ`), and `ASSERT_TRUE`.
117+
118+ To compile this is considerably more complicated because we have to use C++
119+ and we need to include the GoogleTest library:
120+
121+ ```text
122+ g++ -Wall -g -o check_whitespace_test check_whitespace.c check_whitespace_test.cpp -lgtest
123+ ```
124+
125+ Here we're using ` g++ ` instead of ` gcc ` to indicate that we want the C++ compiler.
126+ We've also added the ` -lgtest ` at the end, telling the compiler to include the
127+ ` gtest ` _ library_ (hence the ` -l ` ) when constructing the final executable. Also
128+ note that we're _ not_ including ` main.c ` when we compile the test code;
129+ ` check_whitespace_test.cpp ` contains a ` main() ` function so we _ can't_ include
130+ ` main.c ` (which provides a ` main() ` function), or the system won't know which
131+ one to call.
132+
133+ Assuming your program compiled correctly (again, ** check the output!** ) then you
134+ should be able to run the test code:
135+
136+ ``` {bash}
137+ ./check_whitespace_test
138+ ```
139+
140+ If all the tests pass (and they should initially) you should get something like:
141+
142+ ``` text
143+ $ ./check_whitespace_test
144+ [==========] Running 10 tests from 2 test cases.
145+ [----------] Global test environment set-up.
146+ [----------] 5 tests from strip
147+ [ RUN ] strip.EmptyString
148+ [ OK ] strip.EmptyString (0 ms)
149+ [ RUN ] strip.NoWhitespace
150+ [ OK ] strip.NoWhitespace (0 ms)
151+ [ RUN ] strip.WhitespaceOnFront
152+ [ OK ] strip.WhitespaceOnFront (0 ms)
153+ [ RUN ] strip.WhitespaceOnBack
154+ [ OK ] strip.WhitespaceOnBack (0 ms)
155+ [ RUN ] strip.WhitespaceOnBothEnds
156+ [ OK ] strip.WhitespaceOnBothEnds (0 ms)
157+ [----------] 5 tests from strip (0 ms total)
158+
159+ [----------] 5 tests from is_clean
160+ [ RUN ] is_clean.EmptyString
161+ [ OK ] is_clean.EmptyString (0 ms)
162+ [ RUN ] is_clean.NoWhitespace
163+ [ OK ] is_clean.NoWhitespace (0 ms)
164+ [ RUN ] is_clean.WhitespaceOnFront
165+ [ OK ] is_clean.WhitespaceOnFront (0 ms)
166+ [ RUN ] is_clean.WhitespaceOnBack
167+ [ OK ] is_clean.WhitespaceOnBack (0 ms)
168+ [ RUN ] is_clean.WhitespaceOnBothEnds
169+ [ OK ] is_clean.WhitespaceOnBothEnds (0 ms)
170+ [----------] 5 tests from is_clean (0 ms total)
171+
172+ [----------] Global test environment tear-down
173+ [==========] 10 tests from 2 test cases ran. (0 ms total)
174+ [ PASSED ] 10 tests.
175+ ```
176+
177+ You should make sure you recompile and rerun the tests after you
178+ make changes while fixing the memory leak problems down below. It's
179+ not enough to just fix the memory leaks if you also break the code in
180+ the process, and the tests should help ensure that you're good there.
181+
84182### Using valgrind to find memory leaks
85183
86184One of the more subtle problems with explicit memory management is that
@@ -163,7 +261,10 @@ Note that this tells you where the lost bytes were
163261be * freed* , as that's going to depend on how they're used after they're
164262allocated.
165263
166- There are two types of memory leaks, one of which is frankly easier to
264+ :warning : not all of these output blocks will be useful. Look for ones that
265+ refer to some of _ your_ code somewhere, like ` strip ` or ` is_clean ` .
266+
267+ There are two common types of memory leaks, one of which is frankly easier to
167268sort out than the other.
168269
169270The easy ones are where function ` f() ` allocates _ local_ memory (memory
@@ -194,11 +295,31 @@ test code (you could always just change the test code to say everything
194295passes!), but if the memory leaks to the test code, then that's where the
195296fix has to be made.
196297
298+ :raising_hand : ** Tip:** If you need to free a value and you don't have a
299+ name for it, _ give it one_ . E.g., add an assignment statement like
300+ ` s = value_to_free() ` that gives that value (` value_to_free() ` ) a name
301+ (` s ` ) so you can free it with something like ` free(s) ` . Also, don't forget
302+ how to write clean code just because you're using C. If you find yourself
303+ with multiple functions with the same structure, is there a way you can
304+ write a helper function that captures that structure so you don't have to
305+ repeat it over and over?
306+
307+ Once you have everything happy, you will hopefully get a line like:
308+
309+ ``` text
310+ ==357046== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
311+
312+ ```
313+
314+ at the end indicating that you now have 0 errors and all is well.
315+
197316## What to do
198317
199- - [ ] Compile the program ` check_whitespace.c `
318+ - [ ] Compile the program ` check_whitespace `
200319 and run ` valgrind ` on it to find any leaks it may have (hint: it has at
201320 least one).
321+ - [ ] Also compile ` check_whitespace_test ` and run ` valgrind ` on the test code, to
322+ find any leaks there (there are several).
202323- [ ] In ` leak_report.md ` describe why the memory errors happen, and how to fix them.
203324- [ ] Actually fix the code.
204325- [ ] Commit, push, etc.
0 commit comments