Hey guys

I was wondering how you guys handle error detection for large scale projects?

I wanted the error system to be able to show me the call chain that lead to the error so I could quickly track it down and kill it. So I decided to use the CF to return the error status and wrote some macros that would copy the name of the function and the contents of it's argument list into a debug buffer when an error occurs. After returning to the beginning of the application the debug buffer contains the call chain to the misbehaving function as long as I remebered to check for the error.

I also wanted the debug system to behave in a similar manner to the error system and show me the call chain to the debug problem so we can track down who's sending faulty data. Obviously we don't want to leave the debug code in the release build so it gets removed, which means I use a macro to check the CF. A problem could arise however, the program may run perfectly under debugging but if I accidently used a debug CF check instead of an error CF check the release build could now crash'n'burn. Another problem that could crop up is modifying a function to now return an error CF instead of a debug CF, all calls to the function would need to be updated or the release build could crash'n'burn.

Anything that could break the application when removing debugging is unacceptable.

So I wondered about a blanket error system which required all functions to return the CF. The biggest thing I don't like with this is that every function must do a CF check. I did some quick and dirty timing and the overhead was about 2-4 cycles per call.



MyFunct proc blah
...
clc
@@_exit:
ret
@@_error:
stc
jmp @@_exit
MyFunct endp

invoke MyFunct, 123
jc @@_error


The abvantages are consistant error detection no matter what changes are made to the functions, but the penalties are time and code size increases.

Is this acceptable?
Does anyone have a better/easier solution?
Posted on 2005-02-19 20:03:53 by Maelstrom
Testing, testing, anyone out there?

Come on guys, someone must have an opinion, or don't you bother checking for errors :-D
Posted on 2005-02-21 15:50:43 by Maelstrom
I have 2 large projects :D

I always considered that the best debugger is between my two ears, somthing humans use to call a brain.

When i need thesting i use some macros to output debug information to another window. When i greater doubts is do insert an int 3 at the loactaion and start running step by step using a great debugger named Ollydbg. In those ocasions i do a debug build that contains the names of the procedures and variables and line locations in source code. I can clearly see on the call stack trace the history of calls and their parameters that got me there and i can inspect the data freely.

I usually step by step thru the source and seek for the error (in my logic)

On rare occasions (on my own OS) I do dissasemble my own code using IDA Freeware and check for absolute code positions and segentation.

My debug macros can redirect output to a file if needed.

Basically that is all. I do find syntax or simple miss errors on the spot and very easy without any need for a debugger. And basically most of my errors are algorithmical or logical anyway so I could have used my brain in the first place :-D
Posted on 2005-02-21 18:19:55 by BogdanOntanu

Come on guys, someone must have an opinion, or don't you bother checking for errors :-D


What errors ? :P There are only design considerations that may not meet the end users comprehension.

Seriously, I agree with Bogdan here, there is no substitute for acually thinking out a problem based on what you understand with the code you have written. The closest I come to a dubugger these days is Doctor Watson post mortem debugging where I need to know where it went BANG.

For data testing on the fly to see what an algo is doing, there are a number of ways to output data. The console, title bar, Messageboxes, status bar and you can tailor the output to do what you like in whatever format you like.

With the macro system I have going in MASM its as simple as,



print hex$(value1),32
print str$(value2),13,10


Output is something like,



prompt:/> 0D0A33FE 12345678
Posted on 2005-02-21 18:40:59 by hutch--
For errors, exception handling. It's pretty efficient, as you don't constantly need to check function return values... C++ level exception handling is not very feasible in assembly, though, so I'd say the best you can do is to *always* check return values, even if things "should never fail" ;)
Posted on 2005-02-23 06:17:00 by f0dder
Condition assembly could help?


%MACRO ErrorCodeIs 1 ; %1=conditionCode (NASM syntax)
%IF Debugging ; set to FALSE in release version
J%-1 %%NoError
CALL ErrorHandler
%%NoError:
%ENDIF
%ENDMACRO
....
invoke MyFunct, 123
ErrorCodeIs C


OllyDbg is great in using COFF object symbol table. It attaches to my code when an exceptions occurs and in the code window it replaces numeric addresses of called procedures with their symbolic names. When debugger jumps out due to access violation in my code, I only have to route the failed procedure manually to emergency exit (POPAD, RET) and then I can see in the code window what procedure was called and what were its atguments.
Posted on 2005-02-23 07:53:15 by vit$oft
Hey guys

Thanks for the replys, sorry I haven't posted sooner but I've been busy.

The more I thought about requiring *all* my functions to return the CF and checking it, the more I disliked it. The problem was I was trying to integrate the error detection and debugging systems when they should obviously be seperate. Any function whose sole errors are debugging asserts can't possibly fail once the asserts are removed so why the hell am I still checking the CF.

So, for the error system I'm only going to have functions that can fail return the CF and if I forget to check the CF upon return that's my foobar. Thanks f0dder.

Ok, now the debug system. I currently have macros that can check incoming data and log messages to a console, file, or whatever. The problem is that the bad data is sent, or was set, by a function earlier in the call chain and the debug message doesn't help identify who that was. I could create some tricky macros to track the call chain but I think it'll be easier to simply have the debug macros generate an int3 and let the debugger kick in. Thanks Bogdan and vit$oft.

Now both Bogdan and vit$oft have stated they have ollydbg showing symbol names, arrgh, how the hell did you do that!!! I've never been able to get that to work. So cough up and spill the beans *please*

Oh, and I do agree with Bogdan and hutch, the best debugger is between your ears.
Posted on 2005-02-25 01:37:18 by Maelstrom
Btw, should you need to mix C and assembly code, CF is not the best way of handling errors :)

As for "the best debugger is between your ears" - sure. But I pity those who haven't learned to use debuggers, it makes life so much easier.
Posted on 2005-02-25 01:47:26 by f0dder
Now both Bogdan and vit$oft have stated they have ollydbg showing symbol names, arrgh, how the hell did you do that!!! I've never been able to get that to work. So cough up and spill the beans *please*

Check these threads out:
http://ollydbg.win32asmcommunity.net/index.php?action=vthread&forum=1&topic=40
http://ollydbg.win32asmcommunity.net/index.php?action=vthread&forum=1&topic=451

BTW, last versions of OllyDbg also eats PDB debug info.
Posted on 2005-02-25 02:11:49 by MazeGen
Hey guys

Yay, symbolic information, thanks MazeGen :alright:

f0dder, I code all my stuff in asm so CF will do nicely.
I like to run new code thru my head a few times first before I use the debugger for a proper check. I generally find must foobars before I fire up the debugger, but try debugging without symbolic information, ack, what a pain in the butt!
Debugging will be so much easier now :-D
Posted on 2005-02-25 15:20:58 by Maelstrom
I tend to agree with vit$oft, my projects invariably contain an equate __DEBUG__ equ 0 (or 1) and my suspect code contains the buildtime directive (in many places):


if __DEBUG__
do debugging stuff
endif


This way, I can compile the binary with Debug code in it, and just leave the Debug stuff there until the code is pristine and perfect, then change the equate to 0 and rebuild the binary WITHOUT any debugging code.
I often log stuff to a textfile from my Debug code, so its easy to create a logfile that contains exactly what you are looking for, with another nice option being the ability to timestamp events in your logfile.
It's quite possible to create a number of such logfiles for example when debugging a multithreaded nightmare it can be handy to have a logfile per Thread to separate things a bit, or you might go with an RTF logfile that uses different colors for text lines.
Posted on 2005-03-01 08:19:00 by Homer
Hey EvilHomer2k

My new debug macros are pretty bare bones at the moment but I will add logging at some point, my old macros have it so it's simply a case of cut'n'paste.

It's quite possible to create a number of such logfiles for example when debugging a multithreaded nightmare it can be handy to have a logfile per Thread to separate things a bit, or you might go with an RTF logfile that uses different colors for text lines.


That's a good idea, thanks :alright:
Posted on 2005-03-01 16:16:34 by Maelstrom