Debugging during Coding

Slides:



Advertisements
Similar presentations
11-Jun-14 The assert statement. 2 About the assert statement The purpose of the assert statement is to give you a way to catch program errors early The.
Advertisements

Annoucements  Next labs 9 and 10 are paired for everyone. So don’t miss the lab.  There is a review session for the quiz on Monday, November 4, at 8:00.
Tutorial 12: Enhancing Excel with Visual Basic for Applications
 Both System.out and System.err are streams—a sequence of bytes.  System.out (the standard output stream) displays output  System.err (the standard.
Software Construction 1 ( ) First Semester Dr. Samer Odeh Hanna (PhD) Office: IT 327.
Overview of Previous Lesson(s) Over View  Assertions  assert() library function is declared in the cassert header to check logical conditions in native.
Java Programming, 3e Concepts and Techniques Chapter 4 Decision Making and Repetition with Reusable Objects.
IS 1181 IS 118 Introduction to Development Tools VB Chapter 06.
Computer Programming and Basic Software Engineering 4. Basic Software Engineering 1 Writing a Good Program 4. Basic Software Engineering 3 October 2007.
Guide To UNIX Using Linux Third Edition
C++ fundamentals.
Computer Science 340 Software Design & Testing Design By Contract.
Unit Testing & Defensive Programming. F-22 Raptor Fighter.
11 Values and References Chapter Objectives You will be able to: Describe and compare value types and reference types. Write programs that use variables.
REFACTORING Lecture 4. Definition Refactoring is a process of changing the internal structure of the program, not affecting its external behavior and.
Testing. What is Testing? Definition: exercising a program under controlled conditions and verifying the results Purpose is to detect program defects.
1 Defensive Programming and Debugging (Chapters 8 and 23 of Code Complete) Tori Bowman CSSE 375, Rose-Hulman September 21, 2007.
1 Debugging and Testing Overview Defensive Programming The goal is to prevent failures Debugging The goal is to find cause of failures and fix it Testing.
PROGRAMMING IN VISUAL BASIC.NET VISUAL BASIC BUILDING BLOCKS Bilal Munir Mughal 1 Chapter-5.
Debugging in Java. Common Bugs Compilation or syntactical errors are the first that you will encounter and the easiest to debug They are usually the result.
Testing. 2 Overview Testing and debugging are important activities in software development. Techniques and tools are introduced. Material borrowed here.
Copyright 2003 Scott/Jones Publishing Standard Version of Starting Out with C++, 4th Edition Chapter 13 Introduction to Classes.
Introduction to Exception Handling and Defensive Programming.
1.  Writing snippets of code that try to use methods (functions) from your program.  Each snippet should test one (and only one) function......by calling.
Writing a Run Time DLL The application loads the DLL using LoadLibrary() or LoadLibraryEx(). The standard search sequence is used by the operating system.
Fall 2002CS 150: Intro. to Computing1 Streams and File I/O (That is, Input/Output) OR How you read data from files and write data to files.
Java Programming, 2E Introductory Concepts and Techniques Chapter 4 Decision Making and Repetition with Reusable Objects.
 2003 Prentice Hall, Inc. All rights reserved. 1 IS 0020 Program Design and Software Tools Preprocessor Midterm Review Lecture 7 Feb 17, 2004.
Exceptions and Assertions Chapter 15 – CSCI 1302.
SWE 4743 Abstract Data Types Richard Gesick. SWE Abstract Data Types Object-oriented design is based on the theory of abstract data types Domain.
Defensive Programming. Good programming practices that protect you from your own programming mistakes, as well as those of others – Assertions – Parameter.
Chapter 13 Recursion Copyright © 2016 Pearson, Inc. All rights reserved.
Chapter 1.2 Introduction to C++ Programming
Programming in visual basic .net Visual Basic Building Blocks
Chapter 6 CS 3370 – C++ Functions.
Introduction to Linked Lists
Error Handling – the Debug and Trace Classes
Chapter 13: Pointers, Classes, Virtual Functions, and Abstract Classes
Key Ideas from day 1 slides
Defensive Programming
Introduction to C++ Systems Programming.
Java Programming Language
Chapter 8 – Software Testing
Chapter 13 - The Preprocessor
Testing and Debugging.
Coding Defensively Coding Defensively
The Pseudocode Programming Process
LESSON 20.
Important terms Black-box testing White-box testing Regression testing
The dirty secrets of objects
Software Construction
Topics Introduction to File Input and Output
Design and Programming
Chapter 6 Methods: A Deeper Look
Lecture 22 Inheritance Richard Gesick.
Verification and Validation Unit Testing
Register Variables Declaring a variable as a "register" variable is an advisory to the compiler to keep the normal location of the variable in a register,
CSE 303 Concepts and Tools for Software Development
Test Case Test case Describes an input Description and an expected output Description. Test case ID Section 1: Before execution Section 2: After execution.
Exception Handling Imran Rashid CTO at ManiWeber Technologies.
Tonga Institute of Higher Education
Computer Science 340 Software Design & Testing
Topics Introduction to File Input and Output
CMSC 202 Exceptions 2nd Lecture.
CMSC 202 Exceptions.
Review for Midterm 3.
Software Construction
C++ Object Oriented 1.
IS 135 Business Programming
Defensive Programming
Presentation transcript:

Debugging during Coding (based on Chapter 3 of Debugging Applications by John Robbins) Divyanand M. Kutagulla Dept. of EECS Syracuse University dkutagul@syr.edu

Overview Introduction Assert, Assert, Assert and Assert How and What to Assert Assertions in .NET Windows forms or Console Applications Assertions in Native C++ Applications

Introduction What is it??? Proactive Programming Mindset Unit Testing

What is it??? A.K.A. Proactive Programming A different mindset… Done by the Developer Proactive Programming Defensive Programming An error occurred Why did it occur? A different mindset…

Proactive Programming Mindset AVOID using the debugger as much as possible Each time an error occurs don’t step through every line unless you really have to… Make the code 'debug itself ' Accurately trace its execution flow Provide as much information as possible about an error: What happened? Why did it happen? Where did it happen?

Unit Testing Developer tests his/her module. Execute as much as of the code as possible Confirm specs are implemented Code doesn’t crash Requires Proactive Programming Mindset

Assert, Assert, Assert and Assert Assertions –The Idea… Assertion Implementation Cardinal Rule of Assertions (CROA) Hallmarks of a good Assertion Benefits of Assertions A Final Note…

Assertions-The Idea… Validate the developer’s design intent Definition: "...an assertion declares that certain condition must be true at a specific point in the program“ -John Robbins

Assertion Implementation Either a function (.NET) or a macro (C/C++) typically executed in debug builds Some means to notify the developer / tester / customer that some condition failed (message box / writing message directly to output)

Cardinal Rule of Assertions (CROA) Assertions MUST NOT change the program's state in any way whatsoever! Maintain identical behavior of Debug and Release versions of code Program’s state Stack Memory Variables … (That is why assertions are implemented as macros in C/C++. If they were C/C++ functions, they would modify the stack, thus disturbing the program’s state and violating the CROA!!!)

Hallmarks of a good Assertion Information about where and why a given condition is invalid Lets us observe the program state right when the error occurs Invoke the debugger (usually…)

Benefits of Assertions ‘Precision’ Debugging: we don’t have to step through code that we don’t want to Additional documentation at level of developer’s assumptions/intentions ‘Executable Assumptions/Intentions’ Caveat: Never replaces regular documentation

A Final Note… Use Assertions in addition to Error Checking //CORRECT: Check Your error conditions after ASSERTing them bool str_copy(char* pStrFrom, char* pStrTo, size_t numChars) { //Assert the input params first… assert(pStrFrom != NULL); assert(pStrTo ! =NULL); assert(numChars > 0)); //Now actually do the error checking… if(NULL == pStrFrom) return false; if(0 == numChars) }

How and What to Assert How to Assert? What to Assert Correct ways to use assertions What to Assert Identifying conditions/assumptions that are good candidates for assertions Conditional Compilation techniques

How to Assert…? While checking multiple conditions, assert one condition at a time Will be able to pinpoint exactly which sub-condition failed. Applies when multiple conditions are joined by a mutual conjunction (see code snippets in following slides)

Assert one condition at a time… //INCORRECT: Writing assertions to check all conditions at once bool str_copy(char* pStrFrom, char* pStrTo,size_t numChars) { //DON'T do this assert((pStrFrom != NULL) && (pStrTo ! =NULL) && (numChars > 0)); //perform character string copying... } //CORRECT: Writing assertions to one condition at a time bool str_copy(char* pStrFrom, char* pStrTo, size_t numChars) //DO do this assert(pStrFrom != NULL); assert(pStrTo ! =NULL); assert(numChars > 0));

How to Assert…? (cont’d) Check the condition completely Assert against specific values if needed Easily catches corner cases (see code snippets in following slide)

Assert condition completely… //we assume that the customer name passed in is a valid nonempty //string //INCORRECT: Incompletely asserting conditions bool lookup_customer(string* pStrName) { //DON’T ONLY do this assert(pStrName != NULL); //access database... } //CORRECT: Completely asserting conditions //DO ALL of these assert(*pStrName != "");

What to Assert…? Input parameters into our modules Especially parameters coming from outside modules that we have not developed Needn’t assert parameters multiple times Especially private methods of a module But, asserting them would help to catch bugs internal to our modules…

What to assert…? (cont’d) Method return values… Indicates a problem right when it occurs Practice commonly ignored! Assumptions A simple assertion isn’t enough May need conditional compilation techniques to help verify some assumptions NOTE: The techniques must neither cause any change in program state nor cause any behavioral difference in the Debug code and Release code

Conditional Compilation Techniques C/C++ Use #ifdef #ifdef DEBUG //can also be any symbol… //some assertion code goes here… #endif .NET Use the [Conditional(“DEBUG”)] attribute before the method definition

Assertions in .NET Windows Forms or Console Applications .NET Debugging Facilities The Debug.Assert Method Collecting and Recording Debug Output .NET TraceListeners StackTrace Information Customizing Assertion Behavior Assertions in Native C++

Assertions in .NET Windows Forms or Console Applications The VERIFY Macro Visual C++ Assertions

.NET Debugging Facilities System.Diagnostic namespace class: Debug Active only if the DEBUG symbols are defined during compilation Both classes have Assert Method!!! Use the Debug.Assert method for assertions Assertions active only in Debug builds

The Debug.Assert Method Three overloaded versions: public static void Assert(bool); Checks for a condition and outputs the call stack if the condition is false. public static void Assert(bool,string); Checks for a condition and displays a message if the condition is false. public static void Assert(bool,string,string); Checks for a condition and displays both specified messages if the condition is false. (source: .NET Framework documentation 1.1.0)

Collecting and Recording Debug Output Done using the TraceListener object Stored in the Debug object’s Listener collection Extensible way to define custom logging DefaultTraceListener in the Debug object logs to two standard places: Assertion Message Box OutputDebugString: used by the attached Debugger

.NET TraceListeners TextWriterTraceListener EventLogTraceListener Logs Assertions and debug messages to a specified log file EventLogTraceListener Logs above outputs to a event log However, they don’t log the stack trace Stack trace VERY useful during debugging But we can get the stack trace at any point: StackTrace st = new StackTrace();

User defined TraceListeners Can derive from the TraceListener class or the TextWriterTraceListener class Derive from the TextWriterTraceListener class to redirect the output to a Stream (an array of bytes) Derive from the TraceListener class and add an EventLog instance to write to Event Log(s) (“…which record information about important software or hardware events” (source: .NET Framework documentation 1.1.0)

User defined TraceListeners (cont’d) Override the Fail methods to emit messages the listeners Need to get the listeners listening first… Override the Write/WriteLine methods to actually record messages Debug object automatically calls the method each time a message is to be written.

StackTrace Information… StackTrace is an ordered collection of StackFrame objects representing the runtime call stack. It is a stack… StackFrame “…represents a function call on the call stack for the current thread.” (source: .NET Framework documentation 1.1.0) Use it to obtain file name and line number information Can also get the function parameter list to figure out exactly which method of which type was called.

Customizing Assertion Behavior Shut off assertion message boxes Set the assertuienabled attribute (under the assert element) to false in the application configurationb file Provide a file to log assertion output Provide a file name to the logfilename attribute (again under the assert element in the application configuration file (NOTE: the assert element is under system.diagnostics element)

Customizing Assertion Behavior (cont’d) Add/remove new TraceListeners Set the add/remove attribute of listeners element to a string name of the desired TraceListener object. While adding a listener, we need to specify the the type and the initializer values to be passed to the listener’s constructor (NOTE: listeners element also comes under the trace element which comes under the system.diagnostics element in application configuration file)

Example app.config file <configuration> <system.diagnostics> <assert assertuienabled="false" logfilename="traelog.txt" /> <trace> <listeners> <add name="someTraceListner" type="fully qualified typename" initializeData="some data to be passed in" <remove name="Default" </listeners> </trace> </system.diagnostics> </configuration>

Assertions in Native C ++ Use the assert macro defined in assert.h Extra functions in Windows platforms: GetObjectType IsBadCodePtr IsBadReadPtr IsBadStringPtr IsBadWritePtr IsWindow

Assertions in Native C++ More readable assertions in C++ Provide a logical AND operator and the string Can be used when asserting return values //CORRECT: Check Your error conditions after ASSERTing them bool str_copy(char* pStrFrom, char* pStrTo, size_t numChars) { //check for error return code if (NULL_STRING(pstrTo)) assert(!”str_copy(): source string pointer is NULL!”); //alternatively can also do this… assert( (FALSE == (pStrTo != NULL)) && “str_copy(): source string pointer is NULL!” ); //… }

The VERIFY Macro A check that stays in the release build Normal assertion based checks ‘disappear’ in the release builds. If the check fails in the release build, the application still crashes Still need to make sure some sort of error recovery technique is provided Used mainly in MFC code

Visual C++ Assertions assert macro defined in ASSERT.H Portable across all compilers/platforms Console App: output goes to stderr (typically the screen…) GUI App: output goes to a dialog box Output: assertion failed in file <name> in line <num>

Visual C++ Assertions _ASSERT macro defined in CRTDBG.H Typically used on development on Windows platforms Same as standard assert macro _ASSERTE also in CRTDBG.H Identical to _ASSERT Additionally, it also includes the text of the failed expression (useful to make our assertions as descriptive as possible)

Visual C++ Assertions ASSERT_KINDOF (MFC) Checks whether a valid pointer to a class derived from CObject is actually an instance of that class or a class derived from that class Assumes a valid pointer is passed in…

Visual C++ Assertions ASSERT_VALID (MFC) Checks whether a pointer to an object of a class derived from CObject is actually a valid pointer. (i.e only checks for pointer being non NULL pointer) It then calls the AssertValid method of this object to check the object internal state. The implementer of class shall override the method inorder to define custom checks.

One bad thing about Visual C++ Assertions… They violate the CROA!!! They modify the error code so GetLastError will return the error code put in when the assertion failed…

SUPERASSERT A very souped up version of ASSERT Includes: The type of failure: ASSERT/VERIFY Expression that caused the failure The location of that failure (filename and location) Last error value (GetLastError) A more descriptive message is provided How many times this assertion has failed?

SUPERASSERT (cont’d) Option to ignore assertion Abort the program Break into the Debugger

Trace, Trace, Trace and Trace The Idea… A handy tool: DebugView Tracing in Windows forms and Console .NET applications

The Idea… Tracing the execution flow of the code. A.K.A Helps us to track down any data stream related problems A.K.A printf style debugging (C) cout style debugging (C++) Get an idea about the state of application when any error occurs…

A handy tool: DebugView Monitors any calls to the OutputDebugString or kernel mode DbgPrint. Thus we can run this tool alongside an app on a machine that doesn’t have a debugger installed. “It also can burrow its way across machines so we can monitor from a single machine, all machines part of a distrubuted system” (Robbins) Developed by Mark Russinovich, freely available from http://www.sysinternals.com

Tracing in Windows forms and Console .NET applications .NET Tracing Facilities The Four Musketeers The TraceSwitch Object Tracing in Native C++

.NET Tracing Facilities System.Diagnostic namespace classes: Trace Active only if the TRACE symbols is defined during compilation VS.NET defines this by default for Both debug and release projects Four key methods (The Four Musketeers)…

The Four Musketeers Write: (4 overloads): WriteLine (4 overloads): “Writes information about the trace to the trace listeners in the Listeners collection.” (source: .NET Framework documentation 1.1.0) WriteLine (4 overloads): Same as above except that it outputs a carriage return at the end (useful to have readable traces)

The Four Musketeers WriteIf (4 overloads): WriteLineIf (4 overloads): Same as write except that the output is written only if the condition (specified in argument list) is true Conditional tracing WriteLineIf (4 overloads): Same as above except that it inserts a carriage return at the end of the output

TraceSwitch Object Dynamically control the tracing output without needing to recompile (.NET Documentation 1.1.0) Four tracing levels 0: Off 1: Errors are traced 2: Warnings and Errors 3: Information (In addition to warnings and errors) 4: Verbose (everything!!!)

TraceSwitch Object Allows us to control the tracing levels through the application configuration file Configuration file Example file in following slide…

Application Configuration file <system.diagnostics> <switches> <add name="mySwitch" value="0" /> <add name="myNewSwitch" value="3" /> <remove name="mySwitch" /> <clear/> </switches> </system.diagnostics> </configuration>

Tracing in Native C++ Done through the TRACE macro Active only the Debug build version of the code Calls the OutputDebugString so that we can see the output in the debugger These calls occur in the kernel mode, so this can be performance hit for release code… In-fact Windows was sped up by removing quite a bit of traces (DLL load conflict message)

Comment, Comment Comment and Comment The Commenting Mantra Commenting Guidelines for functions General commenting guidelines

The Commenting Mantra “Code as if whoever maintains your code is a violent psychopath who knows where you live” Francios Poulin as quoted by John Robbins

Commenting Guidelines for functions What the function does function Assumptions What each input parameter is expected to contain What each output parameter is epected to contain on success or on failure Each possible return value Exceptions directly thrown

Commenting Guidelines for functions Non self documenting code needs to be documented An interesting algorithm deserves a complete description

General commenting guidelines Bugfixes Bug number and a description of the bug fixed Well placed trace statements, good naming conventions Comment so that the code will be as obvious to you five years down the road as it is now Avoid commented out segments of code

Unit Testing The Idea… Unit Testing strategies

The Idea… “Scaffolding that is put in place to call the code outside the normal program as a whole to verify the code performs as expected” (Robbins) Similar to the test stubs that we write in our code for our courses Developer verifies the code himself/herself

Unit Testing strategies Unit test development in parallel with the application code development Write stubs once the interface is finalized. Write test program (harness) that calls these stubs. Allows incremental testing Think about how to test the code before writing it. Helps to make code more reusable and testable

Unit Testing strategies Strive for Code Coverage Percentage of lines executed in the code Only way to ensure the reliability of a line of code is to execute it…

DONE AT LAST… WHEW!!!

Questions?