Peter N Lewis wrote:
>> I have a lot of assertions. If one of them fails, GPC only reports
>> something like "assertion failed (error #306 at 40dd45)". How can I
>> find out the exact assertion that failed?
>
>
> Rather than use the built in assertions, we use our own assertions,
> that way it allows us to compile them out of the later beta/final
> builds (a requirement for over-asserting as recommended by Writing
> Solid Code which should be essential reading for any programmer).
>
> The code we use is basically:
>
> Prefix file:
>
> {$definec do_debug true}
>
> {$ifc do_debug}
> {$definec Assert(b) AssertCode((b), __FILE__, __LINE__)}
> {$definec AssertNoErr(err) AssertNoErrCode((err), __FILE__, __LINE__)}
> {$definec InitAssertions(name, version) InitAssertionsCode(name,
> version)}
> {$elsec}
> {$definec Assert(b)}
> {$definec AssertNoErr(err)}
> {$definec InitAssertions(name, version)}
> {$endc}
>
>
> Assertions unit:
>
> unit MyAssertions;
>
> interface
>
> {$ifc do_debug}
> procedure AssertCode( b: Boolean; const sourceFileName: String;
> sourceFileLine: Integer );
> procedure AssertNoErrCode( err: OSStatus; const sourceFileName:
> String; sourceFileLine: Integer );
> procedure InitAssertionsCode( const name: String; const version:
> String );
> {$endc}
>
> implementation
>
> {$ifc do_debug}
>
> var
> gAppName: String255;
> gAppVersion: String255;
>
> procedure InitAssertionsCode( const name: String; const version:
> String );
> begin
> gAppName := name;
> gAppVersion := version;
> end;
>
> procedure AssertCode( b: Boolean; const sourceFileName: String;
> sourceFileLine: Integer );
> begin
> if not b then begin
> WriteLn( 'Assert: ' + gAppName + ' ' + gAppVersion + ' - '
> + sourceFileName + ':' + NumToStr( sourceFileLine ) );
> end;
> end;
>
> procedure AssertNoErrCode( err: OSStatus; const sourceFileName:
> String; sourceFileLine: Integer );
> begin
> if err <> noErr then begin
> WriteLn( 'Assert: Error=' + NumToStr(err) + ' ' + gAppName
> + ' ' + gAppVersion + ' - ' + sourceFileName + ':' + NumToStr(
> sourceFileLine ) );
> end;
> end;
>
> {$endc}
>
>
> Obviously this can easily be extended to implement assertions any way
> you desire.
>
> Please be aware that if you intend to compile out assertions (as you
> should for at least some assertions), then you must never include real
> code in your assert statement, eg:
>
> Assert( (open( ... )) == 0 );
>
> Rather you need to do
>
> err = open( ... );
> Assert( err == 0 );
>
> Why do you have to compile out some assertions? Because you should be
> doing things like:
>
> Assert( ValidDataStructure( complex_structure ) );
>
> Where ValidDataStructure is walking through your complex structure
> ensuring it is all internally self consistent, which could be a
> significantly time consuming task. But that does not matter as it
> will be compiled out when you are performance tuning and in the
> shipping version.
>
> The alternative is you would have to be very light weight with what
> you assert, or have two different classes of assertions (perhaps by
> using something like)
>
> {$ifc do_heavy_debug}
> Assert( ValidDataStructure( complex_structure ) );
> {$endc}
>
> Enjoy,
> Peter.
>
Thank you for this detailed solution.
Bastiaan.