Presentation is loading. Please wait.

Presentation is loading. Please wait.

Debugging during Coding

Similar presentations


Presentation on theme: "Debugging during Coding"— Presentation transcript:

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

2 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

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

4 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…

5 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?

6 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

7 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…

8 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

9 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)

10 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!!!)

11 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…)

12 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

13 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) }

14 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

15 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)

16 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));

17 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)

18 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 != "");

19 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…

20 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

21 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

22 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++

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

24 .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

25 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)

26 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

27 .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();

28 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)

29 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.

30 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.

31 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)

32 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)

33 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>

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

35 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!” ); //… }

36 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

37 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>

38 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)

39 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…

40 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.

41 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…

42 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?

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

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

45 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…

46 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

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

48 .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)…

49 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)

50 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

51 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!!!)

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

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

54 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)

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

56 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

57 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

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

59 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

60 Unit Testing The Idea… Unit Testing strategies

61 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

62 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

63 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…

64 DONE AT LAST… WHEW!!!

65 Questions?


Download ppt "Debugging during Coding"

Similar presentations


Ads by Google