Data races caused by unsynchronized accesses to shared data have long been the source of insidious errors in concurrent software. They are hard to identify during testing, reproduce, and debug. Recent advances in race detection tools show great promise for improving the situation, however, and can enable programmers to find and eliminate race conditions more effectively.
This tutorial explores dynamic analysis techniques to efficiently find data races in large-scale software. It covers the theoretical underpinnings, implementation techniques, and reusable infrastructure used to build state-of-the-art data-race detectors (as well as analyses targeting other types of concurrency errors). The tutorial provides industrial case studies on finding data races and closes with a discussion of open research questions in this area.
Recent years have witnessed a surge of interest in symbolic execution for software testing, due to its ability to generate high-coverage test suites and find deep errors in complex software applications. In this tutorial, we give an overview of modern symbolic execution techniques, discuss their key challenges in terms of path exploration, constraint solving, and memory modeling, and present several tools implementing these techniques.