cooperative-software-develo.../debugging.html

167 lines
12 KiB
HTML
Raw Normal View History

2017-04-16 20:59:49 +02:00
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
2020-08-29 21:44:53 +02:00
<!-- Bootstrap requires jQuery -->
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<!-- Load some Lora -->
<link href="https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet">
2017-04-16 20:59:49 +02:00
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<link rel="stylesheet" href="style.css" />
<title>Debugging</title>
</head>
<body>
<p><a href="index.html">Back to table of contents</a></p>
<img src="images/swatter.png" class="img-responsive" />
<small>Credit: public domain</small>
<h1>Debugging</h1>
2019-09-24 23:16:36 +02:00
<div class="lead">Amy J. Ko</div>
2017-04-16 20:59:49 +02:00
2019-04-30 20:07:02 +02:00
<p>
Despite all of your hard work at design, implementation, and verification, your software has failed.
Somewhere in its implementation there's a line of code, or multiple lines of code, that, given a particular set of inputs, causes the program to fail.
How do you find those defective lines of code?
You debug, and when you're doing debugging right, you do it systematically (<a href="#zeller2">Zeller 2009</a>).
2019-04-30 20:15:53 +02:00
And yet, despite decades of research and practice, most developers have weak debugging skills, don't know how to property use debugging tools, and still rely in basic print statements (<a href="#beller">Beller et al. 2018</a>).
2019-04-30 20:07:02 +02:00
</p>
2017-04-16 20:59:49 +02:00
2019-04-30 20:19:49 +02:00
<p>
To remedy this, let's discuss some of the basic skills involved in debugging.
</p>
2019-04-30 20:11:52 +02:00
<h2>Finding the defect</h2>
<p>To start, you have to <strong>reproduce</strong> the failure. Failure reproduction is a matter of identifying inputs to the program (whether data it receives upon being executed, user inputs, network traffic, or any other form of input) that causes the failure to occur. If you found this failure while <em>you</em> were executing the program, then you're lucky: you should be able to repeat whatever you just did and identify the inputs or series of inputs that caused the problem, giving you a way of testing that the program no longer fails once you've fixed the defect. If someone else was the one executing the program (for example, a user, or someone on your team), you better hope that they reported clear steps for reproducing the problem. When bug reports lack clear reproduction steps, bugs often can't be fixed (<a href="#bettenburg">Bettenburg et al. 2008</a>).</p>
2017-04-16 20:59:49 +02:00
<p>If you can reproduce the problem, the next challenge is to <strong>localize</strong> the defect, trying to identify the cause of the failure in code. There are many different strategies for localizing defects. At the highest level, one can think of this process as a hypothesis testing activity (<a href="#gilmore">Gilmore 1991</a>):</p>
<ol>
<li>Observe failure</li>
<li>Form hypothesis of cause of failure</li>
<li>Devise a way to test hypothesis, such as analyzing the code you believe caused it or executing the program with the reproduction steps and stopping at the line you believe is wrong.</li>
<li>If the hypothesis was supported (meaning the program failed for the reason you thought it did), stop. Otherwise, return to 1.</li>
</ol>
<p>The problems with the strategy above are numerous. First, what if you can't think of a possible cause? Second, what if your hypothesis is way off? You could spend <em>hours</em> generating hypotheses that are completely off base, effectively analyzing all of your code before finding the defect.</p>
2019-11-12 21:27:24 +01:00
<p>Another strategy is working backwards (<a href="#ko">Ko & Myers 2008</a>):</p>
2017-04-16 20:59:49 +02:00
<ol>
<li>Observe failure</li>
<li>Identify the line of code that caused the failing output</li>
<li>Identify the lines of code that caused the line of code in step 2 and any data used on the line in step 2</li>
<li>Repeat three recursively, analyzing all lines of code for defects along the chain of causality</li>
</ol>
2019-11-12 21:27:24 +01:00
<p>The nice thing about this strategy is that you're <em>guaranteed</em> to find the defect if you can accurately identify the causes of each line of code contributing to the failure. It still requires you to analyze each line of code and potentially execute to it in order to inspect what might be wrong, but it requires potentially less work than guessing. My dissertation work investigated how to automate this strategy, allowing you to simply click on the fault output and then immediately see all upstream causes of it (<a href="#ko">Ko & Myers 2008</a>).</p>
2017-04-16 20:59:49 +02:00
<p>Yet another strategy called <em>delta debugging</em> is to compare successful and failing executions of the program (<a href="#zeller">Zeller 2002</a>):</p>
<ol>
<li>Identify a successful set of inputs</li>
<li>Identify a failing set of inputs</li>
<li>Compare the differences in state from the successful and failing executions</li>
<li>Identify a change to input that minimizes the differences in states between the two executions</li>
<li>Variables and values that are different in these two executions contain the defect</li>
</ol>
<p>This is a powerful strategy, but only when you have successful inputs and when you can automate comparing runs and identifying changes to inputs.</p>
<p>One of the simplest strategies is to work forward:</p>
<ol>
<li>Execute the program with the reproduction steps</li>
<li>Step forward one instruction at a time until the program deviates from intended behavior</li>
<li>This step that deviates or one of the previous steps caused the failure</li>
</ol>
<p>This strategy is easy to follow, but can take a <em>long</em> time because there are so many instructions that can execute.</p>
<p>For particularly complex software, it can sometimes be necessary to debug with the help of teammates, helping to generate hypotheses, identify more effective search strategies, or rule out the influence of particular components in a bug (<a href="#aranda">Aranda and Venolia 2009</a>).</p>
2019-04-30 20:19:49 +02:00
<p>
Ultimately, all of these strategies are essentially search algorithms, seeking the events that occurred while a program executed with a particular set of inputs that caused its output to be incorrect.
Because programs execution millions and potentially billions of instructions, these strategies are necessary to reduce the scope of your search.
This is where debugging <strong>tools</strong> come in: if you can find a tool that supports an effective strategy, then your work to search through those millions and billions of instructions will be greatly accelerated.
This might be a print statement, a breakpoint debugger, a performance profiler, or one of the many advanced debugging tools beginning to emerge from research.
</p>
2017-04-16 20:59:49 +02:00
2019-04-30 20:11:52 +02:00
<h2>Fixing defects</h2>
2019-04-30 20:27:43 +02:00
<p>
Once you've found the defect, what do you do?
It turns out that there are usually many ways to repair a defect.
How professional developers fix defects depends a lot on the circumstances: if they're near a release, they may not even fix it if it's too risky; if there's no pressure, and the fix requires major changes, they may refactor or even redesign the program to prevent the failure (<a href="#murphyhill">Murphy-Hill et al. 2013</a>).
This can be a delicate, risky process: in one study of open source operating systems bug fixes, 27% of the incorrect fixes were made by developers who had never read the source code files they changed, suggesting that key to correct fixes is a deep comprehension of exactly how the defective code is intended to behave (<a href="#yin">Yin et al. 2011</a>).
</p>
<p>
This risks suggest the importance of <strong>impact analysis</strong>, the activity of systematically and precisely analyzing the consequences of some proposed fix.
This can involve analyzing dependencies that are affected by a bug fix, re-running manual and automated tests, and perhaps even running users tests to ensure that the way in which you fixed a bug does not inadvertently introduce problems with usability or workflow.
Debugging is therefore like surgery: slow, methodical, purposeful, and risk-averse.
</p>
<center class="lead"><a href="index.html">Back to table of contents</a></center>
2017-04-16 20:59:49 +02:00
<h2>Further reading</h2>
<small>
<p id="aranda">Jorge Aranda and Gina Venolia. 2009. <a href="http://dx.doi.org/10.1109/ICSE.2009.5070530">The secret life of bugs: Going past the errors and omissions in software repositories</a>. In Proceedings of the 31st International Conference on Software Engineering (ICSE '09). IEEE Computer Society, Washington, DC, USA, 298-308.</p>
2019-04-30 20:15:53 +02:00
<p id="beller">Beller, M., Spruit, N., Spinellis, D., & Zaidman, A. (2018, May). <a href="https://doi.org/10.1145/3180155.3180175">On the dichotomy of debugging behavior among programmers</a>. In 2018 IEEE/ACM 40th International Conference on Software Engineering (ICSE) (pp. 572-583).<p>
2017-04-16 20:59:49 +02:00
<p id="bettenburg">Nicolas Bettenburg, Sascha Just, Adrian Schr&oumlter, Cathrin Weiss, Rahul Premraj, and Thomas Zimmermann. 2008. <a href="http://dx.doi.org/10.1145/1453101.1453146">What makes a good bug report?</a> In Proceedings of the 16th ACM SIGSOFT International Symposium on Foundations of software engineering (SIGSOFT '08/FSE-16). ACM, New York, NY, USA, 308-318.</p>
<p id="gilmore">Gilmore, D. (1991). <a href="http://www.sciencedirect.com/science/article/pii/000169189190009O">Models of debugging</a>. Acta Psychologica, 78, 151-172.</p>
2019-09-24 23:16:36 +02:00
<p id="ko">Amy J. Ko and Brad A. Myers. 2008. <a href="http://dx.doi.org/10.1145/1368088.1368130">Debugging reinvented: asking and answering why and why not questions about program behavior</a>. In Proceedings of the 30th international conference on Software engineering (ICSE '08). ACM, New York, NY, USA, 301-310.</p>
<p id="murphyhill">Emerson Murphy-Hill, Thomas Zimmermann, Christian Bird, and Nachiappan Nagappan. 2013. <a href="http://dl.acm.org/citation.cfm?id=2486833">The design of bug fixes</a>. In Proceedings of the 2013 International Conference on Software Engineering (ICSE '13). IEEE Press, Piscataway, NJ, USA, 332-341.</p>
2017-04-16 20:59:49 +02:00
<p id="yin">Zuoning Yin, Ding Yuan, Yuanyuan Zhou, Shankar Pasupathy, and Lakshmi Bairavasundaram. 2011. <a href="http://dx.doi.org/10.1145/2025113.2025121">How do fixes become bugs?</a> In Proceedings of the 19th ACM SIGSOFT symposium and the 13th European conference on Foundations of software engineering (ESEC/FSE '11). ACM, New York, NY, USA, 26-36.</p>
<p id="zeller">Andreas Zeller. 2002. <a href="http://dx.doi.org/10.1145/587051.587053">Isolating cause-effect chains from computer programs</a>. In Proceedings of the 10th ACM SIGSOFT symposium on Foundations of software engineering (SIGSOFT '02/FSE-10). ACM, New York, NY, USA, 1-10.</p>
2017-04-27 05:47:08 +02:00
<p id="zeller2">Zeller, A. (2009). <a href="https://books.google.com/books?id=_63Bm4LAdDIC&lpg=PP1&ots=TAzo27xsK-&dq=why%20programs%20fail&lr&pg=PP1#v=onepage&q=why%20programs%20fail&f=false">Why programs fail: a guide to systematic debugging</a>. Elsevier.</p>
2017-04-16 20:59:49 +02:00
</small>
<h2>Podcasts</h2>
<small>
<p>Software Engineering Daily, <a href="https://softwareengineeringdaily.com/2016/11/19/debugging-stories-with-haseeb-qureshi/">Debugging Stories with Haseeb Qureshi</a></p>
</small>
2018-03-15 16:14:19 +01:00
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-10917999-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
2017-04-16 20:59:49 +02:00
</body>
</html>