1 / 65

Debugging during Coding

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

Patman
Télécharger la présentation

Debugging during Coding

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


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

  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 • Done by the Developer • 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 • 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(NULL == pStrFrom) return false; if(0 == numChars) return false; }

  14. How and What to Assert • How 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)); //perform character string copying... }

  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 bool lookup_customer(string* pStrName) { //DO ALL of these assert(pStrName != NULL); assert(*pStrName != ""); //access database... }

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

  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): • “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): • 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 • Conditional tracing

More Related