Section 1: Pointers and Debugging #

Dates: September 18 – September 19

Learning Goals 🎯 #

By the end of this section, you will be able to:

  1. Identify pointers/references (as opposed to values) and understand how to leverage them in C. This will help you when completing the course assignments (which all involve pointer-based code in C) and give you a better understanding of how computer memory is organized at a low level.
  2. Start feeling comfortable running programs, and learning how to use GDB to step through simple programs. This will give you valuable debugging skills that will help you complete course assignments more efficiently, and provide skills at using a tool that is widely used in industry.

How section works #

Welcome to CS300 section! We release section material via the CS 300 website (where you’re reading this now) and the cs300-f26-section repository.

To get started with the code: To obtain a local copy of the section code and start using it, we recommend doing the following:

  1. Open a terminal in your course container environment

  2. Go to your home directory:

    cd ~
    
  3. Clone the repository:

    git clone git@github.com:csci0300/cs300-f26-section.git
    
  4. If you use VSCode, go to File > Open Folder and select the sec1 directory inside the repository

**What happens during section: Section instructors will work through the section material at their own pace, stopping at activities, questions, and discussions so students can work through the material together. It’s best if you bring your laptop. Notes from most section activities will be available here after all sections for that week have been held.

Section is meant to be interactive! It works best when students ask questions and help each other out, and sometimes instructors will take the section in an unexpected direction based on student requests. Please speak up — if you have questions from lecture, section is the perfect time to ask! 🙂

You can find the code for this section here.

Discussion: pass by preference, pass by value #

Consider the following program (discussion1.c in the section code). Where do we see pass by reference, and pass by value? What’s the difference?

// discussion1.c
#include <stdio.h>

void add_and_print1(int num) {
    num += 5;
    printf("The number is: %d\n", num);
}

void add_and_print2(int* num) {
    *num += 2;
    printf("The number is: %d\n", *num);
}

int main() {
    int cool_num = 10;

    add_and_print1(cool_num);

    add_and_print2(&cool_num);

    printf("%d\n", cool_num);

    return 0;
}

Debugging Brainstorm #

With your partner, think about your current debugging process.

In the past, when you’ve encountered a bug in a program (e.g., in your intro courses), how did you go about:

  1. figuring out where the bug is coming from; and
  2. deciding how to go about fixing the bug?

Take a few notes on techniques you’ve used successfully (or unsuccessfully!) in the past.

The Debugger’s Tool: GDB ⚡️⚡️ #

GDB (GNU Debugger) is an essential resource for debugging in this course, and getting comfortable with using it will save you time during projects. GDB is also very widely used in industry to debug code in all sorts of languages (not just C), so learning it now will help you in future courses and jobs!

GDB allows you to run through your code line-by-line (or by sections that you create) and print useful information. Once you begin debugging in Question 1, we’ll provide you with a list of helpful commands.

Demo: Intro to GDB (and running programs)! 🧙 #

Here’s a program that performs some pointer operations to increment an integer variable, but contains a bug that relates to pass-by-value and pass-by-reference.

// discussion2.c
#include <stdio.h>

void increment_by_value(int x) {
   x = x + 1;
}

int main() {
   int my_number = 1;
   increment_by_value(my_number);


   printf("my number is %d\n", my_number); // BUG:  why not two?!?!?!?!?!
}

To start, let’s build and run the program. We’ll show you how this works, but here’s the steps:

  1. Open a terminal in your sec1 directory
  2. Compile the program with make. This runs the compiler, and creates an executable for each .c file: this file contains the machine code the processor can run!
    • Run ls to see the executables!
  3. Run the program with ./discussion2
    • What does it print? Is this what we expected??

Once we run the program, we’ll demonstrate how to use GDB to step through the program and see what’s happening.

Why are we doing this? This program is pretty short–you might be able to see the bug without using GDB at all! This is great, but our goal here is to give you practice with GDB–particularly on a program you can otherwise understand–so you get a feel for the tool in a comfortable environment. Then, you’ll have a foundation to use it for more complex programs, where it isn’t as easy to see the bug yourself!

Exercise: run and debug some programs #

We’ve provided two “exercise” programs (exercise1.c, exercise2.c) for you to try running and debugging on your own. Both programs involve similar concepts to what we’ve seen here, and both contain bugs. For each program:

  1. Compile and run the program
  2. Run the program in GDB and try to observe the error. As you do this, a good strategy is to consider:
  • What is the goal of this program?
  • What actually happens when you run it?
  • Why does this happen?

The last part is where GDB can be most helpful. Even if you see the bug up-front, try to use GDB to demonstrate why the bug happens, which will help you practice!

See the table in the next section for a reference on some helpful commands!

Quick reference: helpful GDB Commands! #

Below are a list of common commands and what they do (you can reference the full GDB guide here, which is also on the course website):

CommandShortcutDescription
gdb [program]—Starts GDB on your executable file (your compiled .c file). If you don’t see it, run make.
layout srcla srcFormats your code file so you can easily read what line(s) of code GDB is about to execute.
breakpoint [line # or function name]bSets a breakpoint at the given location. When running gdb, execution will stop before this line.
runrExecutes all lines of code from the beginning of the file until the first breakpoint (or the end of the file if there aren’t any).
continuecExecutes all lines of code from wherever execution stopped until the next breakpoint (or end of file)
backtracebtPrints out a debug message of all active function calls that have led to the current state in the file, including when execution errors or crashes.
print [variable name or expression]pPrints out the value of a variable or expression involving a variable (such as a dereference).
nextnExecutes the current line. If this is a function call, executes all functionality within the function.
stepsExecutes the current line. If this is a function call, stop before executing lines inside the function.

Creative Commons Licence This work is licensed under a Creative Commons Attribution 4.0 International License.