This page is designed to provide some tools and tips for debugging your assignments in CSE 333. As this course has a considerable amount of programming, it is recommended to consider different tools and options when approaching and handling bugs in your development process.
Firstly, here are some initial tips to approach debugging:
Secondly, debugging C/C++ programs might be quite different from your experience debugging other programs, especially if you're using GDB when you're more used to a graphical debugger, so we have provided some guides to handle different tools in C and C++:
Please also take a look at the links provided in the navigation bar under “Debugging” that give more robust documentation for valgrind and gdb!
Walking through your program is a good way to compare your expectations for your program's execution and the reality of the current implementation. Finding where the two diverge from each other can provide the scope in which a bug in your program may exist. Here are some things to keep in mind:
However, be wary that the size and complexity of programs make program walkthrough difficult, so utilizing tools such as gdb will help you “walkthrough” an execution of your program!
Debugging is difficult when you do not know where the bug is in the code. “Fail fast” is a methodology to recognize and notify developers about bugs early in development through testing the expected execution of a program. Here are some ways to incorporate this into your programming:
Verify333(boolean)
to
ensure the truth about a statement. However, please make sure
to remove these checks after fully developing the code and
want to submit!We encourage collaboration in this course! Oftentimes, bugs can be easily overlooked individually, so collaboration allows more perspectives, ideas, and just another pair of eyes when developing! Here are some ideas to consider:
Please review the academic conduct section in the syllabus on what differentiates collaboration and cheating.
printf
DebuggingDebugging with printf
is a good starting point when
debugging your program. The idea of printf
debugging
is that it can be a fairly straightforward approach towards
better understanding the state and execution of your program.
Here are some places where it might be useful:
printf
can be a great way to get started, finding
more complex bugs is a lot easier with a dedicated
debugger like GDB.
Valgrind is a memory error detector tool. You should use this in every homework and exercise to check for possible memory errors. Valgrind can also be used to check for appropriate reading and writing into memory! Here are some examples:
Generally, if there is an unexpected output in your solution or a segmentation fault, a quick way to check for possible errors is through Valgrind.
Here is a sample error for illegal reads or writes that you may receive from running Valgrind:
... ==235179== Invalid read of size 4 ==235179== at 0x401183: main (valgrind-tutorial.c:16) ==235179== Address 0x520b068 is 20 bytes after a block of size 20 alloc'd ==235179== at 0x4C360A5: malloc (vg_replace_malloc.c:380) ==235179== by 0x40115E: main (valgrind-tutorial.c:8) ...
When reading this error, the first line will explain the type of invalid access as well as an associated stack trace in the next line. Starting at the third line, there is a stack trace of which block of memory you may be referring to.
Here is an example error for not freeing all memory from the heap when running Valgrind:
... ==235179== HEAP SUMMARY: ==235179== in use at exit: 20 bytes in 1 blocks ==235179== total heap usage: 3 allocs, 2 frees, 1,064 bytes allocated ==235179== ==235179== 20 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==235179== at 0x4C360A5: malloc (vg_replace_malloc.c:380) ==235179== by 0x40115E: main (valgrind-tutorial.c:8) ==235179== ==235179== LEAK SUMMARY: ==235179== definitely lost: 20 bytes in 1 blocks ==235179== indirectly lost: 0 bytes in 0 blocks ==235179== possibly lost: 0 bytes in 0 blocks ==235179== still reachable: 0 bytes in 0 blocks ==235179== suppressed: 0 bytes in 0 blocks ...
There will be information on lost blocks of memory, which means you have not free'd them before the end of the program execution.
LEAK SUMMARY
, you want to ensure that
“definitely lost” and “indirectly
lost” are 0 to make sure there were no memory leaks
in your code!getaddrinfo()
later in the course (ex10,
ex11, hw4) will result in a leakage that is “still
reachable”. Disregard this leakage as it is a bug in
the <netdb.h>
library rather than your
code.
GDB (Gnu DeBugger) is a tool that will help debug your C and C++ programs. Although this tool may have been used in CSE 351 primarily for assembly, CSE 333 uses GDB more to walk through source code and analyze the program state throughout its execution. GDB allows:
printf
statements.Please also refer to gdb manual and the gdb cheatsheet attached on the nav bar!
Here are some additional compiled tips that the staff have when working with gdb:
backtrace
displays the program stack. This may
be particularly helpful for getting more information on
program failures (e.g., segmentation fault)break <function/line number> # break on a function or program line break <filename>:<function/line number> # break at a specific file
step
and next
allow you to walk
through your program execution. Remember that
step
steps into function calls and
next
steps over function callsx
and p
: Both are ways to
view the state of any location in memory like a variable,
location in memory, or parameter. Note that x
examines memory at an address expression while p
shows the value of an expression (which you may find more
helpful in this course).
Visit the gdb cheat sheet for
more details (such as printing format specifiers).Learning how to view binary files is particularly helpful later
in the quarter with Homework 3 and Exercise 11 since we'll be
doing a variety of activities that will require reading and
writing binary. Primarily, a tool to help you start reading
binary files is xxd
!
[attu]$ echo -ne "hello world\xca\xfe\xf0\x0d" > test.bin [attu]$ xxd test.bin 00000000: 6865 6c6c 6f20 776f 726c 64ca fef0 0d hello world....
Let's discern between the three pieces of information in this single line (generally with larger files you will see a lot of lines, but still in this format. Follow the same tips described here):
00000000:
) represents the
left-most index of the line (in hex). This can be helpful for a
longer file.68
to be the first-byte value!68
, is the
hex code value for h
. For the last four bytes,
there's just a .
, which means the byte
doesn't correspond to a printable ASCII character.For very long files, xxd
just dumping the content
to the console can be rather unhelpful. You can use a program
called less
which acts as a pager, allowing you to
scroll up and down through the output of xxd
like
so:
xxd <file name> | less