emacs
You can compile programs with the GNU Compiler Collection
gcc
from within
emacs
. Thus you do not have to leave the editor in order to test your
programs. Further,
emacs
remembers your compile command within the current session, so you
don't even have to retype the command whenever you want to compile
your code.
Example:
Edit your code from last lab by typing emacs ctest.c at your prompt.
Enter the
emacs
compilation comand by pressing:
M-x compile
emacs
displays its default compilation command (
make -k
) at the bottom of its window:
File Edit Options Buffers Tools Minibuf Help /* * ctest.c * * Created on: 2011-01-03 * Author: David Brown */ #include <stdio.h> int main() { char letter; for (letter = 'A'; letter <= 'z'; letter++) { printf("%c\n", letter); } return 0; } ----:---F1 ctest.c (CAbbrev)--L1--All------------------------------- Compile command: make -k
Change this compilation command to gcc -g -o ctest ctest.c :
----:---F1 ctest.c (C Abbrev)--L1--All-------------------------------
Compile command: gcc -g -o ctest ctest.c
emacs
reports the results of compilation within a message window:
File Edit Options Buffers Tools C Help /* * ctest.c * * Created on: 2011-01-03 * Author: David Brown */ #include <stdio.h> int main() { char letter; ----:---F1 ctest.c (C Abbrev)--L1--Top------------------------------- cd ~/CP367/ gcc -g -o ctest ctest.c Compilation finished at Sun Jan 16 10:58:50 ----:**-F1 *compilation* (Compilation:exit [0])--L1--All------------------ (No files need saving)
If there are no compilation errors, close the message window by
typing
C-x 1
(i.e. instruct
emacs
to display only one window.)
To test the program, exit emacs and enter ./ctest at the unix prompt.
gdb
Within
emacs
The GNU Debugger
gdb
is a powerful program that can be used to step through and debug
programs compiled with
gcc
.
gdb
can also be used from within
emacs
, allowing your to test and see the code you are testing at the same
time.
Return to
emacs
by once again typing
emacs ctest.c
at your unix prompt.
We want to split the emacs window so that the source code is visible in one window, the debugger runs in another window, and the execution results in a third window. To do this:
emacs
window into three horizontal parts. All three parts contain the
source code for ctest.c. The cursor stays in the
current window. (Use C-x 3 to create
vertical windows.)
emacs command line now displays the message: Run gdb (like this): gdb -i=mi ctest
press Enter to start the debugger in a
window.
gdb
is now ready to accept commands:
File Edit Options Buffers Tools Gud Complete In/Out Signals Help /* * ctest.c * * Created on: 2011-01-03 * Author: David Brown */ #include <stdio.h> int main() { char letter; ----:---F1 ctest.c (C Abbrev)--L1--Top------------------------------- Current directory is ~/CP367/ GNU gdb 6.6 Copyright (C) 2006 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-pc-solaris2.10"... (gdb) ----:**-F1 *gud-ctest* (Debugger:run)--L9--All---------------------------
Breakpoints are simply points in a program where you can break its execution, allowing you to examine the current state of the running program. Breakpoints are executable lines in the source code where you choose to have the program execution stop until you allow it to continue executing. Breakpoints are extremely helpful in tracing a program's execution and finding errors in that execution.
Breakpoints are set in the program source code. To set a breakpoint
on a given line of source code, move to that line and instruct
emacs
to set a breakpoint there. For this example:
printf("%c\n", letter);
The
emacs
command line now displays the message
Command: break ctest.c:12
.
(Note that the line number may vary from this example,
depending how you entered the program source code.):
----:**-F1 *gud-ctest* (Debugger:run)--L10--All--------------------------
Command: break ctest.c:12
You may set multiple break points in a program. You may turn breakpoints on and off at any time during debugging. Breakpoints are numbered in the order in which they are defined.
To remove a breakpoint, return to the line with the breakpoint and press C-x C-a C-d
Now that that a breakpoint is set, you can run the program from within the debugger.
(gdb)
prompt. (You are now executing a gdb command, not an emacs
command.
The program now executes only up to the first breakpoint set. This
line is marked with a
=>
in the top source code window, and
gdb
displays the message
Breakpoint 1, main () at ctest.c:12
.
File Edit Options Buffers Tools Gud Complete In/Out Signals Help */ #include <stdio.h> int main() { char letter; for (letter = 'A'; letter < 'z'; letter++) { => printf("%c\n", letter); } return 0; } ----:---F1 ctest.c (C Abbrev)--L12--Bot------------------------------ Starting program: /home/dbrown/CP367/ctest ctest warning: Temporarily disabling breakpoints for unloaded shared library "/usr/li\ b/ld.so.1" Breakpoint 1, main () at ctest.c:12 (gdb) ----:**-F1 *gud-ctest* (Debugger:run)--L15--Bot--------------------------
You may now run the program within the debugger and issue various
commands to examine the state of the program. Issue these commands
at the
(gdb)
prompt in the bottom debugger window. Some of these commands are:
The
display
allows you to examine the value of a variable at any point in the
program. The sample program has only one variable,
letter
. Like breakpoints,
display
ed variables are numbered in the order in which they are defined.
This list of
display
ed variables is often called a watchlist.
Type display letter to print its value, as in this example:
----:---F1 ctest.c (C Abbrev)--L12--Bot------------------------------
Starting program: /home/dbrown/CP367/ctest ctest
warning: Temporarily disabling breakpoints for unloaded shared library
"/usr/li\
b/ld.so.1"
Breakpoint 1, main () at ctest.c:12
(gdb) display letter
1: letter = 65 'A'
(gdb)
Note the the
1:
in front of the reference to
letter
.
next
tells the debugger to execute the next line in the program. This
allows you, should you so desire, to step through the entire
program one line at a time. The line that is executed is the line
currently marked with the
=>
symbol in the upper source code window. If the program has any
output it displays it in the lower debugger window. The value of
any variable chosen with
display
is displayed in the debugger window immediately after any output.
In the following example the next command has been issued twice:
File Edit Options Buffers Tools Gud Complete In/Out Signals Help */ #include <stdio.h> int main() { char letter; for (letter = 'A'; letter <= 'z'; letter++) { => printf("%c\n", letter); } return 0; } ----:---F1 ctest.c (C Abbrev)--L12--Bot------------------------------ (gdb) display letter 1: letter = 65 'A' (gdb) next A 1: letter = 65 'A' (gdb) next Breakpoint 1, main () at ctest.c:12 1: letter = 66 'B' (gdb) ----:**-F1 *gud-ctest* (Debugger:run)--L24--Bot--------------------------
Note that if a executed line requires user input,
gdb
will wait for you to enter that input, but will not provide a
prompt other than one that the program itself provides.
undisplay tells the debugger to stop displaying the value of the variable numbered n - i.e. to remove that variable from the watchlist.
Type
undisplay 1
to stop displaying the value of
letter
within the debugger window:
File Edit Options Buffers Tools Gud Complete In/Out Signals Help */ #include <stdio.h> int main() { char letter; => for (letter = 'A'; letter <= 'z'; letter++) { printf("%c\n", letter); } return 0; } ----:---F1 ctest.c (C Abbrev)--L11--Bot------------------------------ (gdb) next Breakpoint 1, main () at ctest.c:12 1: letter = 66 'B' (gdb) undisplay 1 (gdb) next B (gdb) ----:**-F1 *gud-ctest* (Debugger:run)--L27--Bot--------------------------
cont (continue) tells the debugger to execute the program up to the next breakpoint, as opposed to stepping through the program one one at a time using next . This is useful if breakpoints are spaced widely within a program an you are interested in examing the state of the program only at those breakpoints. You may not always want to step through an entire program one line at a time.
print tells the debugger to print the value of expression , where expression is a valid expression that can be evaluated by the debugger. Like the breakpoints and the display variables these expressions are numbered by the debugger.
In this example, the debugger is asked to evaluate and display the value of the expression letter + 3 :
File Edit Options Buffers Tools Gud Complete In/Out Signals Help */ #include <stdio.h> int main() { char letter; for (letter = 'A'; letter <= 'z'; letter++) { => printf("%c\n", letter); } return 0; } ----:---F1 ctest.c (C Abbrev)--L12--Bot------------------------------ (gdb) cont Continuing. G Breakpoint 1, main () at ctest.c:12 (gdb) print letter + 3 $1 = 75 (gdb) ----:**-F1 *gud-ctest* (Debugger:run)--L57--Bot--------------------------
quit tells the debugger to stop executing the program. You may get a warning message that the program is still running. You may exit anyways. If the program exited normally, there is no warning message.
C-x k
kills the gdb buffer.
Start debugging
ctest.c
again. This time, put a breakpoint at the line:
char letter;
and examine its value before the line containing the
for
loop is executed.
(Initializing variables when they are declared is a good idea - as is done in the next sample program.)
Enter and demonstrate to the Lab Instructor that you can debug the
following program
heat.c
:
/*
* heat.c
*
* Created on: 2011-01-08
*/
#include <stdio.h>
int main() {
int height = 0; // height of a tree in feet
int radius = 0; // radius of a tree in feet
int requirement = 0; //cubic fee of wood to heat house for one day
int volume = 0; // volume of the tree in cubic feet
int days = 0; // number of days tree will heat house
double PI = 3.1416; // value of pi
// Input.
printf("How tall is the tree (ft): ");
scanf(" %d", &height);
printf("Radius of the tree (ft): ");
scanf(" %d", &radius);
printf("Wood to heat house for one day (ft^3): ");
scanf(" %d", &requirement);
// Computations.
volume = height * radius * radius * PI;
days = volume / requirement;
printf("Volume: %d ft^3\n", volume);
printf("Days: %d\n", days);
return 0;
}