The Simplest debug and trace method Win+Lin 32/64 bit

Post your FreeBASIC tips and tricks here. Please don’t post your code without including an explanation.
ppf
Posts: 88
Joined: Oct 10, 2017 6:41

The Simplest debug and trace method Win+Lin 32/64 bit

Postby ppf » Apr 13, 2020 17:14

Hi,

as title says, this is a perfect, easy and quick way to detect a problem point in sources.
If crashes, frozen app, bad program flow, or so.Base idea is well known, to log events into the logfile,
what I used for years.Now added immediate write with macro.

Surprisingly, because of Kovid-19 sad days with a lot of free time, I decided to find out finally a yearly
omitted minor bug in my oldest app, sGui featured.Success ! (Just only some kind of flashing, flipping help
gadget visibility was there randomly.)
Due matured code I didn't remember, which part of code is safe, tested and well working.No docs, notes.
Also I am not familiar with compiler error codes yet.
Then I decided to expand debug logs into the logfile not only for variable values in problem points, but for
whole app flow marking on important places - in/out Sub-Funcs-Macros points and decision ways in If-Loops
to see program flow.After app's runtest I opened the logfile.What I saw there was unbelievable.
The best part of code I thinked in problematic place was the worst ! Executed every time thru loop..
Whole problem (logical bug) solved in a half hour pleasantly /;D

What I want to say.If you don't use some debugger.Usable for any app, any level of build stage.Easy.Rapid speed.
You see everything important. Pleasant logfile size. After a few weeks upgrading of all my apps to this new
debug method I had a max that filesize cca 4,5 MB.Nice.And amazing is that you don't need to read all, just
jump to the end of logfile to see what happened before the crash.Then, if not yet clear what is wrong, only add
a new log point to trace flow.
If I see nothing bad and close to crashpoint, I mark every line to figure out, which line is bad.This leads to success.
This whole method consist only of a few things used in an app sources.
- to add logfile in core routines module
- write important events, places, flags, variables and values into it
(not needed to log whole program, in case you use this method for the first time, just log things near to the crashpoint
which you visually saw before app crash, huh)
- to add macro 'fileflush' - write to harddisk IMMEDIATELY
https://freebasic.net/forum/viewtopic.php?f=7&t=27627
- optionally used keywords 'Typeof' and 'Sizeof'
- optionally used log polling source method (viz math polling interval method, here polling source with filelogs
in incremental way => compile>run>poll source between last logpoint and crashpoint>add new file logpoint and repeat this process again)

Base principle democode, for example (32bit):

Code: Select all

REM  next 4 lines placed in core routines module, as first thing to do
Dim Shared As String logFileName:logFileName="appLogfile.txt"   
dim shared as integer logFN: logFN=freefile      
open logFileName for output as #logFN      
#define fileflush(fileID) fflush(cast(FILE ptr, Cast( FILE Ptr, FileAttr( fileID, fbFileAttrHandle ))))     

'write #logFN,"some event .. in/out/value/name/place":fileflush(logFN)      'log important events on important places

REM mark in-out points of procedures to see which is broken
#macro myMakro_1()
 write #logFN,"myMakro_1() .. IN":fileflush(logFN)
  'body
  'of
  'macro
 write #logFN,"myMakro_1() .. Out":fileflush(logFN)
#endmacro

function myFunction_a() as byte
 write #logFN,"myFunction_a() .. IN":fileflush(logFN)      
  'body
  'of
  'function        
 write #logFN,"myFunction_a() .. Out":fileflush(logFN) 
end function

Sub mySub_I()
 write #logFN,"myFunction_a() .. IN":fileflush(logFN)      
  'body
  'of
  'sub
 write #logFN,"myFunction_a() .. Out":fileflush(logFN) 
End Sub

REM mark decision ways in IF blocks to see program flow
Do
'...
 
  write #logFN,"something=",'value of something'     'add YOUR correct expression/variable value here !
  fileflush(logFN)   
 if 'something' then
  write #logFN,"if 'something' .. ",str(something):fileflush(logFN) 
   'commands
 elseif 'another thing' then
  write #logFN,"elseif 'another thing' .. ",str(another thing):fileflush(logFN)   
   'commands 
 else
  write #logFN,"else .. ":fileflush(logFN)   
   'commands   
 end if
'...
Loop

Enjoy it !
Last edited by ppf on May 10, 2020 9:54, edited 1 time in total.
paul doe
Posts: 1255
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: The Simplest debug and trace method

Postby paul doe » Apr 13, 2020 21:15

Sorry, but it looks tremendously cumbersome to use to me, for something so simplistic:

Code: Select all

#include once "crt.bi"
#include once "vbcompat.bi"

type _
  DebugInfo
 
  public:
    declare constructor( _
      byref as const string )
    declare destructor()
   
    declare const sub _
      print( _
        byref as const string )
     
  private:
    as long _
      _fileHandle
end type

constructor _
  DebugInfo( _
    byref aFileName as const string )
 
  _fileHandle => freeFile()
 
  open aFileName _
    for output _
    as _fileHandle
 
  this.print( _
    "** App started on: " + _
      format( now(), "yyyy-mm-dd" ) ) + " " + _
      format( now(), "hh:nn:ss" ) + " **"
end constructor

destructor _
  DebugInfo()
 
  if( _fileHandle <> 0 ) then
    this.print( _
      "** App finished on: " + _
      format( now(), "yyyy-mm-dd" ) ) + " " + _
      format( now(), "hh:nn:ss" ) + _
      " **"
   
    close( _fileHandle )
  end if
end destructor

sub _
  DebugInfo.print( _
    byref aString as const string )
 
  ? #_fileHandle, aString
 
  fflush( cptr( FILE ptr, _
    fileAttr( _fileHandle, fbFileAttrHandle ) ) )
end sub

static shared as const DebugInfo _
  Debug => DebugInfo( "app_log.txt" )

sub _
  sub1()
 
  Debug.print( "sub1()" )
 
  '' Do something
 
  Debug.print( "end sub1" )
end sub

'' Main

Debug.print( "main()" )

'' Start main program
sub1()

Debug.print( "end main" )
bcohio2001
Posts: 553
Joined: Mar 10, 2007 15:44
Location: Ohio, USA
Contact:

Re: The Simplest debug and trace method

Postby bcohio2001 » Apr 15, 2020 0:51

Mine is even more simple, just a sub.
And by using a #Define to enable or disable.
Also a log file size limiter.

Code: Select all

'#Define __DebugFileOn__
#Include "string.bi"
#Include "vbcompat.bi"
Sub DebugFile(FName As String, Note As String)
   'if not defined then will do nothing!
   #Ifdef __DebugFileOn__
   Dim As Integer DFile, FileCnt,KB
   Dim As Double LastLog
   Dim As String CheckIt, NextCheck
   '
   KB = 30 'this can be changed any time
   'check size of file, if getting large, make new file (infinite loop or A LOT of errors ????)
   'skip over older files!!!
   Do
      FileCnt += 1
      If FileCnt > 1 Then
         CheckIt = NextCheck
      Else
         CheckIt = ExePath + "\" + FName + ".txt"
      EndIf
      'append # to name
      NextCheck = ExePath + "\" + FName + "-" + Str(FileCnt+1)+ ".txt"
      If FileExists(NextCheck)=0 Then
         'check size of last used file
         If FileLen(CheckIt) > KB * 1024 Then CheckIt = NextCheck
         Exit Do
      EndIf
   Loop
   LastLog = 0
   If FileExists(CheckIt) Then
      LastLog = FileDateTime(CheckIt)
   EndIf
   DFile = FreeFile
   Open CheckIt For Append As #DFile
   If Int(Now) > Int(LastLog) Then
      'new date
      If Lof(DFile) Then Print #DFile, "" 'blank line -- will not add if a "new" file
      Print #DFile, String(10,"-");" ";
      Print #DFile, Format(Now,"mmmm d, yyyy");
      Print #DFile, " ";String(10,"-")
   EndIf
   Print #DFile, "At ";
   Print #DFile, Format(Now,"h:mm:ssam/pm");
   Print #DFile, " ";Note
   Close #DFile
   #EndIf
End Sub
ppf
Posts: 88
Joined: Oct 10, 2017 6:41

Re: The Simplest debug and trace method

Postby ppf » May 03, 2020 16:16

Thank you both for your versions, very inspirative!
Also I found badidea's Gamelog routine in my unsorted old archive.
https://freebasic.net/forum/viewtopic.php?f=15&t=27299#p256605
Date&timestamp in logfile was thing on my todo list, permanently omitted for a long time.
Sothat now added too.
Finally I decided to encapsulate debugin routines to 'debug.bi' file (placed into FB '/inc' folder),
aka new system file.
Also added simplest tracking macro 'ss(a)' for visual tracking behaviors of WORKING program - points,
vars+values, mice position..


File "debug.bi"

Code: Select all

#include once "crt/stdio.bi"      'fflush
   'flush ANY file !!
#define fileflush(fileID) fflush(cast(FILE ptr, Cast( FILE Ptr, FileAttr( fileID, fbFileAttrHandle ))))

Dim Shared As String logFileName:logFileName="appLogfile.txt"   
dim shared as integer logFN: logFN=freefile     
open logFileName for output as #logFN     
Dim  Shared As Boolean debugMode
debugMode = True   'to False  change onTheFly via Gui setup dialog for example
#Macro dbg(a)
REM for crash hunting
 if debugMode then
   write #logFN,a
   fileflush(logFN)
 end if
#EndMacro
#Macro ss(a)      'aka shotstop in working app withou crashes
REM for visual tracking
'paused track of a single/few codelines to see visual effects of running app
'to catch mostly logical bugs - typos-bad formulas/expression-wrong drawings etc.

 ? "press a key .. " & a:sleep
#endmacro
#Macro closend()
REM close all files and program
 close
 end
#endmacro


Usage - As The FIRST '#include' in app's code.

Code: Select all

#include "debug.bi"
#include "fbgfx.bi"
'other #includes
plus the rest of program

Syntax e.g.

Code: Select all

   dbg("l.999   wizetW,wizetH" & wizetW & "," & wizetH)    'point and 2 vars to logfile if crash, Or
   ss("wizetW,wizetH" & wizetW & "," & wizetH)            ' 2 vars on screen if app works, just bad drawings
   dbg("Failed to create image Buck1")   
   
  if multikey(&h3d) then      'cyclin
   ss("a/ event->GetMenuStatus="&event->GetMenuStatus)
    MenuOn(event)
   ss("b/ event->GetMenuStatus="&event->GetMenuStatus)
  end if   
ShawnLG
Posts: 137
Joined: Dec 25, 2008 20:21

Re: The Simplest debug and trace method

Postby ShawnLG » May 03, 2020 17:24

This is the simplest debug and trace method.

Code: Select all

beep 'Insert this statement once in various parts of your code to trace down the program crash. If program beeps before crash. move it further in the program.


A better way is to display variables in question.

Code: Select all

print var1, var2, var3
sleep
end
badidea
Posts: 2129
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: The Simplest debug and trace method

Postby badidea » May 03, 2020 17:44

A simple print is not always possible. For example in games where the whole screen is overwritten a few miliseconds later. And if page flipping is used, it is even more complicated. Sleep can also be a problem is such cases. And beep does not work linux.
caseih
Posts: 1518
Joined: Feb 26, 2007 5:32

Re: The Simplest debug and trace method

Postby caseih » May 03, 2020 18:25

Just write your messages to standard out. Can use regular printf(). Or write them to standard error. That will never get overwritten by graphics frames or the like. And they can be redirected to a file for analysis also. Nearly all Unix applications write debugging messages this way. If you start the program from a GUI environment with no controlling terminal, those messages are never seen. If you run it from a terminal, you can see them. It's a great technique.

Sadly for Windows apps, it doesn't work as well because writing to standard out causes a console window to appear, even when you don't really want it to.
ppf
Posts: 88
Joined: Oct 10, 2017 6:41

Re: The Simplest debug and trace method Win+Lin 32/64 bit

Postby ppf » May 14, 2020 16:09

edit -
Added new two trackin macros for code under sGUI library.But placement that ones seems clearer
in sGUI folder.

Used shortcuts meaning is :
'dbg' aka 'debug'
'ss' aka 'shortstop' trackin debug

For clarification,
this debug method is used for apps compiled as graphical (-s gui compiler switch), not for console apps.
Such usage is unknown in result for me, I didn't develop/test any console app.

If somebody made test with console apps, I 'll be glad to know that result, thanks.

Return to “Tips and Tricks”

Who is online

Users browsing this forum: No registered users and 2 guests