You are on page 1of 28

Unix and Software Tools (P51UST)

Compilers, Interpreters and


Debuggers
Ruibin Bai (Room AB326)
Division of Computer Science
The University of Nottingham Ningbo, China

P51UST: Unix and Software Tools


Introduction

• The role of language translators


• Compilers and Interpreters
• The Java Virtual Machine
• Debugging
– Using print statements to debug a program
– Basic functions performed by a debugger
The role of language translators

• Programming languages have evolved to make


programming easier for humans
• Computers still execute machine code
• Language translators are required to translate
between the two
• A new translator is required for each combination
of programming language and machine-code
The role of language translators (2)

• Translation involves several tasks


– translating high level program statements into
combinations of machine code instructions
– translating high level data structures into
combinations of memory locations
– linking to existing code (libraries, modules, objects,
system calls) to form a final program

• Two broad approaches to translation


– compilation and interpretation
Compilers
• A compiler translates text written in a computer language (the
source language) into another computer language (the target
language).
• Is primarily used for programs that translate source code from
a high-level programming language to a lower level language
(e.g., assembly language or machine language).
• A compiler is likely to perform many or all of the following
operations:
– lexical analysis,
– preprocessing,
– parsing/semantic analysis,
– code generation, and
– code optimization.
Interpreters

• One statement is translated and then executed at a time

Start at the beginning of the program


REPEAT
translate next program statement
if no translation error occurred then execute the statement
UNTIL the end of the program or an error occurs
Compilers: Pros and Cons
• Pros:
– Enable programmers to write human-readable code
with a richer set of instructions
– Program execution is fast
– Compiled programs can be run more than once without
re-compilation
– Programs can be compiled for different platforms

• Cons:
– To run on a different platform, code has to be
recompiled
Interpreters: Pros and Cons

• Pros:
– No need to compile before running the program;
program can just be run straight away
– Program can be run on different platforms without
recompiling (provided an interpreter is available for
that platform)

• Cons:
– Program execution is slower than with compiled code
Java Virtual Machine

• Until the advent of Java, the trend for


programming was moving away from interpreted
languages and towards compiled languages
– Software interpreters are complex and so run slowly

• Java takes a new approach…


Java Virtual Machine (2)

• Java is compiled into a standard machine language


called Bytecode
• This standard machine language is then interpreted by
a software interpreter, the Java Virtual Machine
(JVM)
– JVM takes Bytecode and executes it
– Bytecode is not the standard machine language for any
specific hardware processor
– Any machine which has a JVM can run the compiled
Java program
Advantages of JVM

• Because Java is compiled before being interpreted it


runs more quickly than standard interpreted
languages
• BUT, Java is also portable because the platform it is
compiled for is available for lots of different
machine architectures
– Java therefore does not need to be recompiled to run
on different types of machine
Debugging
Debugging

• A program fails a test case (or a bug is reported).


• A programmer is given the test case and the
associated source code and “debugs” the program
until the fault has been corrected.
• The program, having been fixed, no longer exhibits
the failure.
• The hard part is locating the problem!!
Bridging the Gap

• One problem with faults is that they are not


necessarily located “near” their associated failure.
• We need to “bring the failure close to the fault”.
• The simplest way to do this is with print statements.
Using print Statements

• Your program has compiled but crashes when it


runs. What should you do?
– Sprinkle print statements throughout your program
and see how many are executed.

• Your program runs but is printing the wrong


answer. What should you do?
– Use print statements to print out the values of your
internal variables. See which give you the right
answer and which give you the wrong answer.
A Buggy awk Program

x = 10
while (x > 5) {
x++
}
print $x
Program with print Statements

x = 10
print "Got past initialisation\n"
while (x > 5) {
print "Entered while loop\n"
x++
print "incremented x\n"
}
print "Exited while loop\n"
print $x
Output of Buggy Program

$ awkInfinite.sh
Got past initialisation
Entered while Loop
incremented x
Entered while Loop
incremented x
Entered while Loop
incremented x
Entered while Loop
incremented x
More Print Statements

x = 10
print "Got past initialisation\n"
while (x > 5) {
print "Entered while Loop\n"
print $x ”\n"
x++
print "incremented x\n“
print $x ”\n”
}
print "Exited while loop\n"
print $x
More Output

$ awkInfinite.sh
Got past initialisation
Entered while Loop
10
incremented x
11
Entered while Loop
11
incremented x
12
Debugging Tools

• A debugger allows a programmer to monitor the


internal state of a program while it is executing
(saves putting in and taking out print statements).
• Two types of debugger
– Interpretive
– Direct Execution
Types of Debuggers

• Interpretive Debuggers
– work by reading a program and simulating its
execution one line at a time.

• Direct Execution Debuggers


– work by running the actual program in a special
mode where the debugger can read and write the
program’s memory.
Interpretive Vs. Direct Execution
Debuggers
• Interpretive Debuggers
– Easier to program
– Safer, a program cannot crash the machine (just the
debugger).

• Direct Execution
– Faster
– More accurate, the actual program instructions are
being executed
Two Styles of Use

• Line-at-a-time
– A programmer loads the program into the debugger
and “steps” through the program one line at a time.
– The debugger stops the program after each line and
gives the programmer a chance to check the
program’s variables to see if it is operating correctly.
Two Styles of Use (2)

• Breakpoints
– A Programmer loads a program into the debugger
and specifies “breakpoints” at various locations in
the program.
– The program runs until it hits a breakpoint.
How are Breakpoints Useful?
• If you think you have function that might have a fault.
– Set a breakpoint at the beginning of the function.
– Set another breakpoint at the end of the function.
– If a program’s data is correct at the beginning of the
function but incorrect at the end, then there is a fault in
the function.
– They also allow you to skip over “init” code and
debugged code quickly; letting the programmer focus
on finding the fault.
Editing Variables

• Debuggers let the programmer explore “what-if”


scenarios:
– You can execute a program to a certain point, and
then alter the values of the program’s variables.
– So you can explore unusual cases.
– Plus, if a bug occurs, you can correct an incorrect
value and see how far the program goes before it
encounters another fault.
Summary

• Using a debugger is more flexible than print


statements.
• Debuggers can be used to step through code or to
run until some breakpoint.
• They also let you view the values of variables.
• They take a bit of getting used to but are usually
well worth the time invested.

You might also like