You are on page 1of 18

Innovative Ways to Improve Software Quality

Developing high quality software can be like chasing a mirage - you keep advancing but the goal remains
distant. The buzz says if you're not leveraging the latest methodology or using innovative tools you'll be behind.
However, you may be surprised by what the experts recognize as the key to developing high quality software.
Smart Bear Software invites you to join our expert panel as they share their experience and recommend
approaches to meet the challenges you face in developing high quality software. Find out how the experts:

• Shape, drive or change the development process to ensure the best possible software quality
• Implement practices that lead to better software quality regardless of your development methodology
• Prevent planning and process from slowing development cycles and increasing the chance of errors
resulting in poor software quality
• Believe you can still be innovative even if you are not Agile

THE EXPERTS

Our expert panel will address these and other topics to provide the information you need to ensure your
development efforts result in the highest quality software possible. The panel includes:

Esther Schindler, Host:

Esther Schindler has been writing about technology subjects since 1992, though she wrote her first
program (in FORTRAN) in 1973. She has focused on software development topics and open source for the last
several years, with her by line appearing at CIO.com, ITWorld.com, Software Test & Performance, SD Times,
Informit.com, IT Business Network, and DevSource.com. She’s written market research analyst reports since
2002; she wrote four books (including one that actually paid out its advance) and had her hand in writing or
editing another ten. Esther has owned a computer store, optimized compilers, taught corporate classes about
operating system internals, designed QA tests for Lotus Development (back when 1-2-3 ruled the earth) and in
her first market-research career learned more about General Foods’ Frozen Pudding Pops than any human ought
to know.

Lisa Crispin

An agile testing coach and practitioner, Lisa is the co-author of Agile Testing: A Practical Guide for
Testers and Agile Teams and a contributor to Beautiful Testing and Testen in der Finanzwelt. She also co-wrote
Testing Extreme Programming. Lisa specializes in showing agile teams how testers can add value and guide
development with business-facing tests. For the past ten years, Lisa has worked as a tester on agile teams
developing web applications in Java and .Net. She teaches Agile Testing courses and tutorials worldwide. Lisa
contributes articles to publications such as Better Software magazine, Software Test & Performance Magazine,
IEEE Software Magazine, Methods & Tools, Agile Journal, Agile Record, She enjoys sharing her experiences at

1
conferences and user group meetings around the world. Lisa was named one of the 13 Women of Influence in
testing by Software Test & Performance magazine. For more about Lisa’s work, visit lisacrispin.com.

Jason Cohen

Jason Cohen is the founder of Smart Bear Software, makers of Code Collaborator, the most popular
peer code review tool. He's the author of Best Kept Secrets of Peer Code Review, and the founder of three other
companies including WP Engine and IT Watch Dogs. He blogs regularly at ASmartBear.com.

Steve Berczuk

Steve Berczuk is an engineer and Scrum Master at Humedica where he's helping to build next-
generation SaaS-based clinical informatics applications. The author of Software Configuration Management
Patterns: Effective Teamwork, Practical Integration, he is a recognized expert in software configuration
management and agile software development. Steve is passionate about helping teams work effectively to
produce quality software. He is especially interested in the interactions between architectural and organizational
issues, especially as they relate to helping teams to develop requirements so they are solving the right problems,
understanding how to apply various technologies, and building tools. For more information about Steve, go to
berczuk.com.

Static Analysis Software:

Finding application defects

Static analysis software can help developers and software architects lower the cost of development of
complex software applications. Often defects introduced during the development process are discovered much
later in the release cycle, usually at the point of Functional Testing, System Testing or User Acceptance Testing,
which can add significantly to the development cost. Even worse, the defect may be shipped in software and
devices that are installed on customer sites, with significant associated costs of fixes, patches or recalls. In many
cases some defects might not manifest themselves for years, when the difficulty of fixing the problem is
compounded by the likelihood that the developers who wrote the code have moved on. In the case of code that
does not comply with the architectural design rules, the defect may manifest an incremental scope creep over
time which results in higher maintenance and refactoring costs. Static source code analysis refers to the analysis
of the source code or object code used to build the software application without executing the application under
test, which contrasts with run time or dynamic analysis where the analysis is performed on a executing
application.

Defining Static Source Code Analysis

Static source code analysis refers to the analysis of software that is performed without executing the
application under test. This contrasts with run time or dynamic analysis where the analysis is performed on a

2
executing application. In a static source code analysis the analysis is performed on the source code or object
code used to build the application.

Static and run time analyses each have their respective merits. A run time analysis will allow you to
isolate behaviour that can only be exhibited at runtime, for example where an application takes some form of
real time feed or interrupt. However, to perform a run time analysis will require the execution of the application
and invariably the creation and maintenance of a test data set to cover the use cases required.

It is well understood that the creation and management of test data can be a complex, costly and
difficult task. Static analysis on the other hand will allow you to catch defects, across multiple compile time
execution paths. This is typically performed as part of the software build process, without having to generate use
cases and supporting data. This has the advantage of allowing developers to quickly isolate defects, while they
are working on the code, so that they can be fixed at much lower cost than defects discovered later on in test or
when released to customers.

Static analysis has for many years been used to give insight into metrics such a code complexity. More
recently it has been used for deep analysis for finding bugs, security vulnerabilities, and analysis of software
architecture.

Background on Static Analysis

Static-analysis techniques infer information about software behaviour based on a static representation
of the software. This contrasts with dynamic analysis techniques, which gather information by observing
software as it is running. Because code is analyzed instead of executed, static analysis does not require test
cases. Static analysis can be seen as a two-phase process. The first phase involves extracting semantic
information from the software’s source code. The second phase involves using this information to discover
defects or other properties of interest.

3
Until recently, static-analysis tools were impractical for most developers to deploy across the enterprise. At one
end of the spectrum were tools, such a Lint, that could only check the surface structure of the code. These can be
useful for enforcing coding standards, and for some superficial checks, but they are not powerful enough to
detect many classes of serious problems. This class of tools also generate a large number of false positive
warnings, making it difficult to review their output. At the other end of the tools spectrum were very
sophisticated model checkers. These tools can verify sequencing properties of a system, but cannot be applied
directly to source code, working instead on an abstract model of the system provided in an esoteric language.
Furthermore, model-checking tools have historically suffered from scalability problems. Recently, new tools
have appeared that overcome these obstacles and make it possible to apply sophisticated analyses to large
programs.

Static-Analysis ROI

The benefits of static analysis are based on the following:

Static analysis is able to examine more execution paths than conventional testing

Conventional testing can only check code being executed, so it is only as good as the test cases. For
real-world systems, the number of paths in the program far exceeds the number that can be exercised by testing.
Test suites might achieve 100% statement coverage, but most paths go unexecuted. In contrast, static-analysis
tools examine paths for which no test cases have been written. This explains why static-analysis tools find many
bugs, even in software that has already undergone the most extensive testing. The best static-analysis tools
improve software quality significantly and require little effort to employ. In addition, major improvements in
software security are realised because the root of many vulnerabilities is a coding defect. Attackers often exploit
corner-case program behaviour, exactly the type that a test suite is likely to miss. Static-analysis tools are more
likely to catch such vulnerabilities

Static analysis can be applied early in the development cycle

Static analysis provides significant time and cost savings because it has the ability to identify bugs
early in the development cycle, where they are easier to fix. According to a comprehensive study on software
testing by the US National Institute of Standards and Technology in 2002, coding defects discovered in fielded
products take 10 to 30 times more effort to fix than coding defects found during coding itself. Identifying bugs
as early as possible—right after coding and before system testing—is critical because bugs become far more
costly to fix the farther downstream they are detected. The savings are significant because debugging, testing,
and verification activities can easily range from 50% to 75% of total software development cost. Another
benefit of the time savings is faster time to market. Static analysis quickly identifies problems that take a long
time to debug by hand. Developers avoid getting sucked into a manual debugging black hole and instead are
able to focus on more important and enjoyable tasks. In addition, product development risk is reduced.
According to the National Institute of Standards and Technology “Over 80 percent of errors are introduced in

4
the coding/unit testing stage, but well over half of these errors are not found until downstream in the
development process.”

Static Analysis for finding coding errors

Static analysis tools like Code Sonar work with a configurable compiler, which simulates the real
compiler used to build the application software. The compiler output is then used as a basis of the analysis to
find defects such as memory leaks, uninitialized variables, buffer overruns and null-pointer dereferences.

Static Analysis for software architecture analysis

Static Analysis such as Lattix create a representation of software applications, databases and systems.
Architects and developers can analyse the most complex systems, edit the structure to create what-if scenarios,
and specify design rules, allowing them to formalise and communicate the architecture to the entire
organization. The result is higher quality, improved reliability, and much easier maintenance with an enforced
and visible architecture.

Improve Software Quality with Static Code Analysis Tools


Many software teams use code reviews to ensure that developers are writing correct, secure code that
adheres to the company's design guidelines. These guidelines might outline naming conventions, patterns to use
for accessing data or other external resources, and so on. Many aspects of the code review process are rather
mechanical and can be automated. Static code analysis tools scan through source code or intermediate code and
search for violations of defined design guideline rules.
One such static analysis tool for applications within the Microsoft .NET Framework is FxCop (version
1.36), a free tool created by Microsoft. FxCop analyzes the intermediate code of a compiled .NET assembly and
provides suggestions for design, security, and performance improvements. By default, FxCop analyzes an
assembly based on the rules set forth by Design Guidelines for Developing Class Libraries. The design
guideline rules are divided into nine categories, including design, globalization, performance, and security,
among others. An example of a naming rule is, "Events should not have 'before' or 'after' prefix." If FxCop
identifies an event named Before Update, it will recommend replacing Before Update with a present-tense
version of the event name (namely, Update). You can also plug in a custom rules class that reflects your
company's internal design guidelines.
To analyze an assembly, launch FxCop, create a new project, and add the assembly to the project.
FxCop shows the 200+ rules that are used when analyzing the assembly; you may turn off existing rules or add
your own. Click the Analyze button to begin the analysis. After enumerating the types, classes, methods, and
members of your assembly, FxCop displays the analysis results, which list the offending code and the rule that
was violated. Select a result for a more detailed description and solution.
FxCop is available as a standalone app; it also includes a command-line implementation that makes it
easy to plug into an automated build process. (Code Analysis, a tool much like FxCop, ships with Visual Studio
Team System and is integrated into the Visual Studio shell.) For more on how to use FxCop, see the Bugslayer
columns by John Robbins: "Bad Code? FxCop to the Rescue" and "Three Vital FXCop Rules."

5
FxCop Analyzes an Assembly Based on Rules Set by .NET Design Guidelines
Another static code analysis tool from Microsoft is StyleCop (version 4.3). Whereas FxCop evaluates
design guidelines against intermediate code, StyleCop evaluates the style of C# source code. Style guidelines
are rules that specify how source code should be formatted. They dictate whether spaces or tabs should be used
for indentation and the format of for loops, if statements and other constructs. Example StyleCop rules include:
the body of for statements should be wrapped in opening and closing curly brackets; there should be white space
on both sides of the = and != operators; and calls to member variables within a class must begin with "this.".
StyleCop is not integrated into Visual Studio Team System—you must install it yourself. Executing
StyleCop from within Visual Studio analyzes the source code in the currently opened solution, displaying the
results as warnings in the error list window. StyleCop can also be integrated with MS Build.
While FxCop and StyleCop pinpoint rule violations, the developer is still responsible for implementing
these tools' suggestions. CodeIt.Right (version 1.1) from Sub Main takes static code analysis to the next level by
enabling rule violations to be automatically refactored into conforming code. Like FxCop, CodeIt.Right ships
with an extensive set of predefined rules, based on the design guidelines document mentioned earlier, with the
ability to add custom rules. But CodeIt.Right makes it much easier to create and use custom rules.
Using custom rules in FxCop requires building and compiling a rules class and plugging it into FxCop. With
CodeIt.Right, custom rules are generated from a graphical user interface; defining a new rule entails picking the
base behaviour pattern and then customizing a couple of properties. CodeIt.Right integrates within the shells of
Visual Studio .NET 2003, Visual Studio 2005, and Visual Studio 2008, and offers a command-line
implementation as well.

CodeIt.Right Updates Selected Violations to Conform to Rules


To use CodeIt.Right from within Visual Studio, choose the Start Analysis option from the CodeIt.Right
menu. After the solution is analyzed, CodeIt.Right displays the results in a window within the Visual Studio
IDE, listing each rule violation. This report can be exported to an XML or Microsoft Office Excel file.
CodeIt.Right's biggest benefit is the automatic code refactoring. From the results screen you can check
which violations to fix and then click the Correct Checked button. All changes made by CodeIt.Right are
highlighted within Visual Studio, and the automated changes can be rolled back with the click of a button.
Static code analysis tools provide a fast, automated way to ensure that your source code adheres to
predefined design and style guidelines. Following such guidelines helps produce more uniform code and also
can point out potential security, performance, interoperability, and globalization shortcomings. Static code
analysis tools are not a replacement for human-led code reviews. Rather, they can generate a first pass of the
code base and highlight areas that require more attention from a senior developer.
Price: FxCop (free); StyleCop (free); CodeIt.Right ($250 per user license).

FxCop

.NET Framework 2.0

FxCop is an application that analyzes managed code assemblies (code that targets the .NET Framework
common language runtime) and reports information about the assemblies, such as possible design, localization,

6
performance, and security improvements. Many of the issues concern violations of the programming and design
rules set forth in the Design Guidelines, which are the Microsoft guidelines for writing robust and easily
maintainable code by using the .NET Framework.

FxCop is intended for class library developers. However, anyone creating applications that should
comply with the .NET Framework best practices will benefit. FxCop is also useful as an educational tool for
people who are new to the .NET Framework or who are unfamiliar with the .NET Framework Design
Guidelines.

FxCop is designed to be fully integrated into the software development cycle and is distributed as both
a fully featured application that has a graphical user interface (FxCop.exe) for interactive work, and a command-
line tool (FxCopCmd.exe) suited for use as part of automated build processes or integrated with Microsoft
Visual Studio® .NET as an external tool.

StyleCop Governance:
Microsoft has turned over governance and coordination of the StyleCop project to the community. The
new Coordinator of this project is responsible for managing contributions. Microsoft is not granting any IP
rights to code or other material contributed to this project by third parties. The IP rights to each particular
contribution are granted to you by the respective contributor under the Ms-PL license.

Description

StyleCop analyzes C# source code to enforce a set of style and consistency rules. It can be run from inside of
Visual Studio or integrated into an MS Build project. StyleCop has also been integrated into many third-party
development tools.

Core Principles

• StyleCop provides value by enforcing a common set of style rules for C# code. StyleCop will continue
to ship with a single, consistent set of rules, with minimal rule configuration allowed. Developers can
implement their own rules if they so choose.

• StyleCop ships with the ability to seamlessly integrate with Visual Studio, MS Build, TFS, etc.
Developers are free to implement custom code to integrate StyleCop into other development and
tooling environments, as described in the SDK documentation.

Test Matrix

Test Matrix helps you improve the quality of your code by making test driven development painless and
convenient. Test Matrix is a 3-in-1 application that adds to Visual Studio support for

7
• Unit Testing,
• Code Coverage analysis,
• and Test Profiling

Test Matrix seamlessly incorporates these critical development practices directly into the coding process itself.

Test Matrix supports all the popular .NET languages, so it doesn't matter if you are developing in C#,
VB.NET, or ASP.NET, Test Matrix will improve your ability to write quality, tested software.

Test Runner
Enjoy seamless test driven development experience

• 100% compatible with your existing tests


• Run unit tests as easily as compiling
• Run unit tests directly from Visual Studio
• Create your own test groups
• Automatic code coverage analysis
• Automatic code profiling
• Easily debug your unit tests
• Supports most popular unit testing frameworks: NUnit, MSTest, MbUnit, CsUnit (xUnit is coming)
• Command line support

Test Matrix will change the way you unit test by making it a seamless part of the programming experience. Test
Matrix makes it easy and practical to follow a "code a little, test a little" philosophy. You can run your entire
suite of tests in the background as easily as building your project, or more interactively through the Test
Explorer window. You can even run and debug your tests directly from the editor itself via hot key or context
menu, keeping your hands on the keyboard where they belong. Test results are reflected in the editor itself, as

8
well as a results window, showing you which tests failed, along with where and why. Test Matrix automatically
marks the lines that caused the failures and provides a convenient stack trace explorer.

Code Coverage
Easily track your code coverage

• Track your coverage automatically while you test


• Editor highlighting to see what you are missing
• Export coverage results as XML
• Command line support

Unit tests check the quality of your code, code coverage checks the quality of your unit tests. Without some way
to track your test coverage, there's no way to know how thorough your tests really are. With TestMatrix, code
coverage metrics are collected automatically as you run your unit tests and applications. Code coverage is
highlighted in the editor window, showing you exactly which lines have and have not received testing coverage.
Test Matrix brings coverage into Visual Studio itself, so that the benefits of its feedback becomes a constant part
of the development process. Test Matrix also allows you to review file, class, method, and line level statistics
across the entire solution to identify which classes or methods require additional testing.

Test Profiling
Experience convenient, no nonsense profiling

• Profile your code from within Visual Studio itself


• Continuous profiling at the unit level
• Targeted performance analysis
• Command line support

9
Test Matrix adds test profiling features directly into the IDE, making it easier to use and learn than stand alone
profilers, not to mention much more affordable. Test Matrix automatically collects line level performance
metrics such as hit and object creation counts, memory utilization, and execution time as you test your
application. As with code coverage, feedback appears directly in the Visual Studio's editor, in the form of hot
spots markers and timing bars. Performance and memory utilization data is also rolled up into solution wide
reports for your analysis. These easy to use features allow you to intuitively judge the performance profiles of
individual lines and methods, while you test. When performance and memory usage information is constantly
visible, you'll be surprised by the things you learn about your code and the problems you spot early.

Static program analysis

Static program analysis is the analysis of computer software that is performed without actually
executing programs built from that software (analysis performed on executing programs is known as dynamic
analysis). In most cases the analysis is performed on some version of the source code and in the other cases
some form of the object code. The term is usually applied to the analysis performed by an automated tool, with
human analysis being called program understanding, program comprehension or code review.

The sophistication of the analysis performed by tools varies from those that only consider the
behaviour of individual statements and declarations, to those that include the complete source code of a program
in their analysis. Uses of the information obtained from the analysis vary from highlighting possible coding
errors (e.g., the lint tool) to formal methods that mathematically prove properties about a given program (e.g., its
behaviour matches that of its specification).

It can be argued that software metrics and reverse engineering are forms of static analysis.

A growing commercial use of static analysis is in the verification of properties of software used in
safety-critical computer systems and locating potentially vulnerable code. For example, medical software is
increasing in sophistication and complexity, and the U.S. Food and Drug Administration (FDA) has identified
the use of static code analysis as a means of improving the quality of software[1].

10
Formal methods

Formal methods is the term applied to the analysis of software (and hardware) whose results are
obtained purely through the use of rigorous mathematical methods. The mathematical techniques used include
denotation semantics, axiomatic semantics, operational semantics, and abstract interpretation.

It has been proven that, barring some hypothesis that the state space of programs is finite, finding all
possible run-time errors, or more generally any kind of violation of a specification on the final result of a
program, is undecidable: there is no mechanical method that can always answer truthfully whether a given
program may or may not exhibit runtime errors. This result dates from the works of Church, Gödel and Turing
in the 1930s (see the halting problem and Rice's theorem). As with most undecidable questions, one can still
attempt to give useful approximate solutions.

Some of the implementation techniques of formal static analysis include:

• Model checking considers systems that have finite state or may be reduced to finite state by
abstraction;
• Data-flow analysis is a lattice-based technique for gathering information about the possible set of
values;
• Abstract interpretation models the effect that every statement has on the state of an abstract machine
(i.e., it 'executes' the software based on the mathematical properties of each statement and declaration).
This abstract machine over-approximates the behaviours of the system: the abstract system is thus
made simpler to analyze, at the expense of incompleteness (not every property true of the original
system is true of the abstract system). If properly done, though, abstract interpretation is sound (every
property true of the abstract system can be mapped to a true property of the original system)[2]. The
Frama-c framework and Polyspace heavily rely on abstract interpretation.
• Use of assertions in program code as first suggested by Hoare logic. There is tool support for some
programming languages (e.g., the SPARK programming language (a subset of Ada) and the Java
Modeling Language — JML — using ESC/Java and ESC/Java2, ANSI/ISO C Specification Language
for the C language)

Shape analysis (program analysis)

In program analysis, a shape analysis is a static code analysis technique that discovers and verifies
properties of linked, dynamically allocated data structures in (usually imperative) computer programs. It is
typically used at compile time to find software bugs or to verify high-level correctness properties of programs.
In Java programs, it can be used to ensure that a sort method correctly sorts a list. For C programs, it might look
for places where a block of memory is not properly freed. Although shape analyses are very powerful, they

11
usually take a long time to run. For this reason, they have not seen widespread acceptance outside of universities
and research labs (where they are only used experimentally)

Applications

Shape analysis has been applied to a variety of problems:

• Finding memory leaks, including Java-style leaks where a pointer to an unused object is not nulled out
• Discovering cases where a block of memory is freed more than once (in C)
• Finding dereferences of dangling pointers (pointers to freed memory in C)
• Finding array out-of-bounds errors
• Checking type-state properties (for example, ensuring that a file is open() before it is read())
• Ensuring that a method to reverse a linked list does not introduce cycles into the list
• Verifying that a sort method returns a result that is in sorted order

Example

Shape analysis is a form of pointer analysis, although it is more precise than typical pointer analyses.
Pointer analyses attempt to determine the set of objects to which a pointer can point (called the points-to set of
the pointer). Unfortunately, these analyses are necessarily approximate (since a perfectly precise static analysis
could solve the halting problem). Shape analyses can determine smaller (more precise) points-to sets.

Consider the following simple C++ program.

Item *items[10];
for (int i=0; i<10; i++) {
items[i] = new Item(...); // line [1]
}
process_items(items); // line [2]
for (int i=0; i<10; i++) {
delete items[i]; // line [3]
}

This program builds an array of objects, processes them in some arbitrary way, and then deletes them.
Assuming that the process_items function is free of errors, it is clear that the program is safe: it never references
freed memory, and it deletes all the objects that it has constructed.

Unfortunately, most pointer analyses have difficulty analyzing this program precisely. In order to
determine points-to sets, a pointer analysis must be able to name a program's objects. In general, programs can
allocate an unbounded number of objects; but in order to terminate, a pointer analysis can only use a finite set of
names. A typical approximation is to give all the objects allocated on a given line of the program the same

12
name. In the example above, all the objects constructed at line [1] would have the same name. Therefore, when
the delete statement is analyzed for the first time, the analysis determines that one of the objects named [1] is
being deleted. The second time the statement is analyzed (since it is in a loop) the analysis warns of a possible
error: since it is unable to distinguish the objects in the array, it may be that the second delete is deleting the
same object as the first delete. This warning is spurious, and the goal of shape analysis is to avoid such
warnings.

Summarization and materialization

Shape analysis overcomes the problems of pointer analysis by using a more flexible naming system for
objects. Rather than giving an object the same name throughout a program, objects can change names depending
on the program's actions. Sometimes, several distinct objects with different names may be summarized, or
merged, so that they have the same name. Then, when a summarized object is about to be used by the program,
it can be materialized--that is, the summarized object is split into two objects with distinct names, one
representing a single object and the other representing the remaining summarized objects. The basic heuristic of
shape analysis is that objects that are being used by the program are represented using unique materialized
objects, while objects not in use are summarized.

The array of objects in the example above is summarized in separate ways at lines [1], [2], and [3]. At
line [1], the array has been only partly constructed. The array elements 0..i-1 contain constructed objects. The
array element i is about to be constructed, and the following elements are uninitialized. A shape analysis can
approximate this situation using a summary for the first set of elements, a materialized memory location for
element i, and a summary for the remaining uninitialized locations, as follows:

0 .. i-1 i i+1 .. 9
pointer to constructed object (summary) uninitialized uninitialized (summary)

After the loop terminates, at line [2], there is no need to keep anything materialized. The shape analysis
determines at this point that all the array elements have been initialized:

0 .. 9
pointer to constructed object (summary)

At line [3], however, the array element i is in use again. Therefore, the analysis splits the array into
three segments as in line [1]. This time, though, the first segment before i has been deleted, and the remaining
elements are still valid (assuming the delete statement hasn't executed yet).

0 .. i-1 i i+1 .. 9
free (summary) pointer to constructed object pointer to constructed object (summary)

13
Notice that in this case, the analysis recognizes that the pointer at index i has not been deleted yet. Therefore, it
doesn't warn of a double deletion

Alias analysis:
Alias analysis is a technique in compiler theory, used to determine if a storage location may be
accessed in more than one way. Two pointers are said to be aliased if they point to the same location.

Alias analysis techniques are usually classified by flow-sensitivity and context-sensitivity. They may
determine may-alias or must-alias information. The term alias analysis is often used interchangeably with term
points-to analysis, a specific case.

What Does Alias Analysis Do?

In general, alias analysis determines whether or not separate memory references point to the same area
of memory. This allows the compiler to determine what variables in the program will be affected by a statement.
For example, consider the following section of code that accesses members of structures:

p.foo = 1;
q.foo = 2;
i = p.foo + 3;

There are three possible alias cases here:

1. The variables p and q cannot alias.


2. The variables p and q must alias.
3. It cannot be conclusively determined at compile time if p and q alias or not.

If p and q cannot alias, then i = p.foo + 3; can be changed to i = 4. If p and q must alias, then i = p.foo + 3; can
be changed to i = 5. In both cases, we are able to perform optimizations from the alias knowledge. On the other
hand, if it is not known if p and q alias or not, then no optimizations can be performed and the whole of the code
must be executed to get the result. Two memory references are said to have a may-alias relation if their aliasing
is unknown.

Performing Alias Analysis

In alias analysis, we divide the program's memory into alias classes. Alias classes are disjoint sets of locations
that cannot alias to one another. For the discussion here, it is assumed that the optimizations done here occur on
a low-level intermediate representation of the program. This is to say that the program has been compiled into
binary operations, jumps, moves between registers, moves from registers to memory, moves from memory to
registers, branches, and function calls/returns.

14
Type Based Alias Analysis

If the language being compiled is type safe, the compiler's type checker is correct, and the language lacks the
ability to create pointers referencing local variables, (such as ML, Haskell, or Java) then some useful
optimizations can be made. There are many cases where we know that two memory locations must be in
different alias classes:

1. Two variables of different types cannot be in the same alias class since it is a property of strongly
typed, memory reference-free (i.e. references to memory locations cannot be changed directly)
languages that two variables of different types cannot share the same memory location simultaneously.
2. Allocations local to the current stack frame cannot be in the same alias class as any previous allocation
from another stack frame. This is the case because new memory allocations must be disjoint from all
other memory allocations.
3. Each record field of each record type has its own alias class, in general, because the typing discipline
usually only allows for records of the same type to alias. Since all records of a type will be stored in an
identical format in memory, a field can only alias to itself.
4. Similarly, each array of a given type has its own alias class.

When performing alias analysis for code, every load and store to memory needs to be labeled with its class. We
then have the useful property, given memory locations Ai and Bj with i,j alias classes, that if i = j then Ai may-

alias Bj, and if then the memory locations will not alias.

Flow Based Alias Analysis

Analysis based on flow, unlike type based analysis, can be applied to programs in a language with
references or type-casting. Flow based analysis can be used in lieu of or to supplement type based analysis. In
flow based analysis, new alias classes are created for each memory allocation, and for every global and local
variable whose address has been used. References may point to more than one value over time and thus may be
in more than one alias class. This means that each memory location has a set of alias classes instead of a single
alias class.

Escape analysis:
In programming language compiler optimization theory, escape analysis is a method for determining
the dynamic scope of pointers. It is related to pointer analysis and shape analysis.

When a variable (or an object) is allocated in a subroutine, a pointer to the variable can escape to other
threads of execution, or to calling subroutines. If a subroutine allocates an object and returns a pointer to it, the
object can be accessed from undetermined places in the program — the pointer has "escaped". Pointers can also
escape if they are stored in global variables or other data structures that, in turn, escape the current procedure.

15
Escape analysis determines all the places where a pointer can be stored and whether the lifetime of the
pointer can be proven to be restricted only to the current procedure and/or thread.

Optimizations

A compiler can use the results of escape analysis as basis for optimizations:

• Converting heap allocations to stack allocations. If an object is allocated in a subroutine, and a pointer
to the object never escapes, the object may be a candidate for stack allocation instead of heap
allocation.

• Synchronization elision. If an object is found to be accessible from one thread only, operations on the
object can be performed without synchronization.

• Breaking up objects or scalar replacement. An object may be found to be accessed in ways that do not
require the object to exist as a sequential memory structure. This may allow parts (or all) of the object
to be stored in CPU registers instead of in memory.

Practical considerations

In object-oriented programming languages, dynamic compilers are particularly good candidates for performing
escape analysis. In traditional static compilation, method overriding can make escape analysis impossible, as
any called method might be overridden by a version that allows a pointer to escape. Dynamic compilers can
perform escape analysis using the available information on overloading, and re-do the analysis when relevant
methods are overridden by dynamic code loading.

The popularity of the Java programming language has made escape analysis a target of interest. Java's
combination of heap-only object allocation, built-in threading, and the Sun HotSpot dynamic compiler creates a
candidate platform for escape analysis related optimizations (see Escape analysis in Java). Escape analysis is
implemented in Java Standard Edition 6.

Example (Java)

class A {
final int finalValue;

public A( B b ) {
super();
b.doSomething( this ); // this escapes!
finalValue = 23;
}

16
int getTheValue() {
return finalValue;
}
}

class B {
void doSomething( A a ) {
System.out.println( a.getTheValue() );
}
}

In this example, the constructor for class A passes the new instance of A to B. Do Something. As a result, the
instance of A—and all of its fields—escapes the scope of the constructor.

Some Techniques for Managing Error:

Explicit Design Criteria:


Programmers need guidelines to help them make difficult tradeoffs while programming. At Robelle,
our criteria are reliability first, then compatibility, performance, and finally features. Without such
leadership from management, programmers cannot be expected to produce a consistent and
dependable style of program.

The Development Diary.


This is a computer file that acts as a lab notebook; it records your thoughts and plans as you work on
the code. We make entries for each day, with the most recent day at the start of the file. Other sections
of the file list outstanding bugs, enhancement requests, patches for known problems, and
documentation problems.

Batch Jobs to Test for Stupid Mistakes:


If you touch the code, you may delete a line by mistake. We do automatic batch regression testing of
each new version. The tests are designed to abort if anything goes wrong, or update a results file if
they make it to the end. We often run the test suite every night to check that day's changes. Ideally,
each bug uncovered should be verified with a batch job that reproduces it. Once the bug is corrected,
the test will pass and will ensure that old bugs do not creep back in by accident (this has happened to
us!).

17
Frequent User Testing:

The biggest danger is that you will deliver a working system that doesn't do what the client needs or
wants. Even when your code does what they want, it never does it exactly right on the first pass. To
minimize this risk, we send pre-releases of revised software to selected clients about once a month. A
pre-release program is much like a regular release, including updated manuals and on-line help. We
seek out clients who will treat this software as harshly as they would an official new product, and we
often find them in our tech-support records. The benefit is mutual: we get objective feedback, and the
clients often get very quick solutions to their problems.

Conclusion:
The task of improving software quality is primarily a management task, not a technical one. The
problem is not that we haven't adopted the latest, "perfect" system development methodology -- the problem is
that we haven't been realistic about the immense difficulties in producing quality software, and we haven't been
paying attention to the mundane, practical details of producing software that does what the client actually needs
and wants.

I think that the primary responsibility of managers, the fundamental one around which all others will
revolve, is to break projects into manageable steps, then deliver the new software produced by each step into the
client's hands, so they can give you objective feedback for the next step.

18

You might also like