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

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

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

Post by ppf »

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
Moderator
Posts: 1740
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: The Simplest debug and trace method

Post by paul doe »

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: 556
Joined: Mar 10, 2007 15:44
Location: Ohio, USA
Contact:

Re: The Simplest debug and trace method

Post by bcohio2001 »

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

Post by ppf »

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.p ... 99#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: 142
Joined: Dec 25, 2008 20:21

Re: The Simplest debug and trace method

Post by ShawnLG »

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: 2594
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: The Simplest debug and trace method

Post by badidea »

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: 2158
Joined: Feb 26, 2007 5:32

Re: The Simplest debug and trace method

Post by caseih »

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

Post by ppf »

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.
Post Reply