University of Minnesota
Machine Architecture and Organization (sec 010)
index.php

CSci 2021 Lab 0x2

In today's lab we'll continue doing examples of progamming with C and debugging C programs, and see some examples relating to numbers in binary. As a reminder, lab grades are solely attendance based, so if you are here, work on the lab and then get checked off by a TA, you are fine grade-wise. But if you don't finish the lab activities during the lab period, please consider coming back and working on them later to get more practice. If you have questions about materials from the labs after class, ask them on the Piazza forum or in office hours (information about both of these are on the course web site).

  1. (Fix this Fibonacci #1.)

    [This question is repeated from last week, but we'd recommend working on it today if you haven't already gotten to it.]

    The Fibonacci sequence is a famous series of integers with a very simple construction. The first two numbers are 0 and 1, and every number thereafter is the sum of the previous two numbers, e.g. the third and forth numbers are (0 + 1) = 1 and (1 + 1) = 2. Your friend is writing a Fibonacci generator as their very first C program, but they've made an absolute mess of it! Help them fix their obvious compilation errors and the runtime errors that lurk beneath.

    Get a copy of their program with:

    cp /web/classes/Spring-2020/csci2021/labs/0x2/lab1-fibonacci.c .

  2. (Binary representations in printf and scanf)

    For this question you are going to complete a program that requires some scanf and printf statements. We will also ask you to write a bit of code regarding binary representations. To get the code template:

    cp /web/classes/Spring-2020/csci2021/labs/0x2/binary_template.c .

    You will be printing and scanning in values other than %d in this case. In fact, you will need to print and scan for hexadecimal and octal representations of integers. Every place a scanf or printf is needed will be marked on the template. It is your choice as to the messages you give with your printf statements.

    Once you get all the printf and scanf statements complete, run the program to see if you know your hexadecimal and octal representations well enough. (Note: for input of your guesses, you DO NOT need to use the prefixes, i.e. ‘0x’ for hexadecimal and ‘0’ for octal.)

    Something you might have noticed is that we did not ask for a binary representation. This is because printf and scanf do not have a specifier for binary. In this case, write some code that will print the binary representation of an integer. A more in-depth description is given in the template.

  3. (Fix the malloc with valgrind and gdb)

    For question 3, you will be debugging the Fibonacci program from last week that has had a bunch of mallocs added. This is to help you see some of the mistakes you may later find you've made yourself when trying to use malloc. To get the file:

    cp /web/classes/Spring-2020/csci2021/labs/0x2/fibMalloc_buggy.c .

    The program does not compile or run as it should as the mallocs, frees, etc. are not all used correctly. It is your job to fix them so that the program runs smoothly.

    First, we ask that you get the file to compile. Make sure you add the flags -Wall and -g when doing so. This will allow you to use gdb and valgrind in the next step as well as give all possible warnings when compiling. Both of which will help you.

    After the program compiles, try running it. You should see that it is not doing what it should and may even seg fault. You could just stare at the code but using gdb and valgrind will help you find the problems a bit easier. First, for valgrind, run the following line in the terminal:

    valgrind ./executable

    This should run your program under valgrind which looks at your program’s memory usage. Look to see what kind of messages are brought up, what information it gives, etc. Some basics are error messages, memory used, and the number of frees and mallocs. Based on this, you should be able to fix all the issues.

    As a warning, there may be a message of an invalid free error. This could be due to multiple frees or freeing invalid memory. You can look at the rest of the message to possibly trace where this occurs.

    A quick resource for using valgrind is this tutorial. There's also the official website.

    If you want to try another way to debug a program, you can use gdb. Firstly, make sure you compiled your file with -g. This makes sure there are debugging flags on your program. Next, to run gdb use the command

    gdb -tui ./executable

    You can use gdb without the -tui, but -tui, the text user interface, allows you to look at the relevant code you are working on. You can look at both and see which you prefer.

    Next, to run the program, type run. You’ll see that the screen gets a little messed up when you run certain commands. To fix it, press Control-L.

    To start the debugging, use this command:

    start

    This allows you to run the program and stop at main. The command start replaces setting a breakpoint at main and using the run command. If you want to stop at other functions, you can set a breakpoint with this command:

    break function_name

    NOTE: If you ever go into a library function, such as printf, you an use the command finish to get out.

    After the program has stopped, to keep going, you can either say continue and run the rest of the program, or next and it will move one line in your code. Once you get past the initializations, or to the printf, type the command:

    print i

    You should see that it showed you the value of i without having to add a printf in your program. Whenever you are done with gdb, just use q or quit to exit.

    Now that you know the basics, a helpful guide to gdb is this tutorial. The complete manual can help you with finding other commands you can use in gdb to help you debug.

  4. (Drawing the Mandelbrot set.)

    [This question is repeated from last week]

    You might have already heard of the Mandelbrot set, a well known fractal that has a simple definition in terms of an iterative operation on complex numbers. For the purposes of this problem it's just a pretty picture, but in order to draw that picture you need to complete a program by implementing the operation of multiplication over complex numbers. We'll represent a complex number as an array of two doubles, the first (index 0) for the real part and the second (index 1) for the imaginary part. Copy the framework code with:

    cp /web/classes/Spring-2020/csci2021/labs/0x2/lab1-mandelbrot.c .

    And then complete the program filling in the implementation of the function complex_multiply. Your function should read from the arrays a and b, and write the result of the multiplication to c. If you're not familiar with complex multiplication you can find the definition in the usual kinds of online places.

    You can test your program by running commands like:

    ./lab1-mandelbrot 900 600 >mandelbrot.pgm

    eog mandelbrot.pgm

    Where eog is an image-viewing program. Your result should look like a more detailed version of this: