Tuesday, February 19, 2008

Using Assert

In a project that I herited there is massive use of Assert. Personally I did not use Assert that much, but it has some nice advantages during developing an application. (More info on Assertion in general)

What does it do?
Assert can be used as a debug tool. Assert tests boolean expression, and will halt execution if that expression is not true. If that happens, it will raise an EAssertionFailed exception.

How to use it?
This is an example, how you can use Assert in your code.

procedure TForm3.DoIt(AStringList : TStrings);
begin
Assert(Assigned(AStringList),
'Test ');
ShowMessage(AStringList.Text);
end;

procedure TForm3.Button1Click(Sender: TObject);
begin
DoIt(
nil);
end;

Clicking the button will raise the EAssertionFailed exception:

assert

Generally you don't want that the end users see this message. Therefor you can disable/enable assertion throug the $C directive or your project options dialog. If you disable Assertion, the example code will lead to an Acces violation, so normal exception tracking is needed anyhow.

The Delphi help about Assert:



The $C directive enables or disables the generation of code for assertions in a Delphi source file. {$C+} is the default.



Since assertions are not usually used at runtime in shipping versions of a product, compiler directives that disable the generation of code for assertions are provided. {$C-} will disable assertions.

1 comment:

Jolyon Smith said...

Worth mentioning is that "disabling" ASSERTions doesn't simply prevent or suppress the assertion errors, results in those calls essentially being removed during compilation.

This is important because sometimes people use a test in their ASSERT() condition that has a side-effect that they are relying on.

e.g. (hypothetical)

ASSERT( GetObjectWithID(aID, objRef), 'Object not found')

In this case the boolean result of GetObjectWithID() is expected always to return TRUE, so an ASSERT is used to detect an unexpected FALSE result.

However, GetObjectWithID also returns a reference to an object via a var param.

Disabling ASSERTions in this case will result in GetObjectWithID not being called at all, which is clearly not desirable.

Often the side-effects are not as immediately apparent as this.


The result is that ONE such ASSERT() that features necessary side-effects in your application means you cannot then ever disable assertions for that project, which means your production code carries the "baggage" of assertion checks around with it at all times.

ASSERT is great, but it need to be used with care if you want to be able to turn them on/off at will without inadvertently breaking something.