PDA

View Full Version : Debugging and OS exceptions in external DLL's



Clootie
11-09-2003, 07:52 PM
Problem description: When trying to debug this DirectSound program SoundFX (http://clootie.narod.ru/delphi/download_dx90.html#DSex_SoundFX) I'm getting Delphi popped-up showing what there is exception "EInvalidOp catched in dsdmo.dll at address @@@@. Invalid floating point operation".
But: running the same app out of Delphi IDE shows no problem at all.
Question: how to avoid this (bad) Delphi behaviour?

cairnswm
12-09-2003, 07:18 AM
I had a similar problem with Delphi 6 and the Indy components.

I switched to Delphi 5 and it worked fine :(

Alimonster
12-09-2003, 08:55 AM
I can give a couple of vague hints, but no definite solution. Try looking at Tools->Debugger Options, then somewhere in there (probably the OS Exception tab). That tab controls how the IDE responds to exceptions (breaking or ignoring).

You can also investigate passing the appropriate mask using the Set8087CW function to disable or otherwise hide some FPU exceptions -- but I'm not sure what values to pass in there! Maybe do a google search. This code (http://groups.google.co.uk/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&th=75258e7f7a39651&rnum=5) (in the 2nd post) looks promising for masking off the EInvalidOp error...

Clootie
12-09-2003, 10:28 AM
Ok, manually setting exception related bits of 8087 FPU control register did the trick.
Code I've used is:
[background=#FFFFFF][normal=#000000][number=#0000FF][string=#0000FF][comment=#248F24][reserved=#000000]function MungeFPCW(out pwOldCW: Word): Boolean;
var wTemp, wSave: Word;
begin
Result:= False;
asm
fstcw wSave
end;
if ((wSave and $300) <> 0) or // Not single mode
($3f <> (wSave and $3f)) or // Exceptions enabled
((wSave and $C00) <> 0) then // Not round to nearest mode
begin
asm
mov ax, wSave
and ax, not 300h // single mode
or ax, 3fh // disable all exceptions
and ax, not 0C00h // round to nearest mode
mov wTemp, ax
fldcw wTemp
end;
Result:= True;
end;
pwOldCW:= wSave;
end;

var Old80087: Word;
initialization
MungeFPCW(Old80087);
end.


PS. I've tried playing with Delphi "Debugger Options" dialog before, but it have not helped me (exception is nor longer handled by Delphi, but application is "stuck" somewhere).

Alimonster
12-09-2003, 11:04 AM
If you want to rearrange the code to be more Delphi-like, try something like the following (untested):

function MungeFPCW(out pwOldCW: Word): Boolean;
var
wSave: Word;
begin
Result := False;

wSave := Default8087CW;
pwOldCW := wSave;

if ((wSave and $300) <> 0) or // Not single mode
($3f <> (wSave and $3f)) or // Exceptions enabled
((wSave and $C00) <> 0) then // Not round to nearest mode
begin
wSave := wSave and not $300; // single mode
wSave := wSave or $3f; // disable all exceptions
wSave := wSave and not $C00; // round to nearest mode

Set8087CW(wSave);
Result := True;
end;
end;

var
Old8087: Word;

initialization
MungeFPCW(Old8087);

finalization
Set8087CW(Old8087);

end.

No idea whether the above clearer code works - let me know please!

Note that it's also the programmer's responsibility to restore the CW at the end...

Clootie
12-09-2003, 04:08 PM
>>Note that it's also the programmer's responsibility to restore the CW at the end...
Actually, no. Why I should do it? First, nobody cares about it's default state! Second, you app thread (and it's state) is destroyed anyway after finalization!