This code is supposed to check a setting of the FTDI USB-serial converter driver. It fails when there is no converter in the system. Can you spot the bug?
This code is supposed to check a setting of the FTDI USB-serial converter driver. It fails when there is no converter in the system. Can you spot the bug?
procedure Tf_ArgVideoMainBase.CheckFtdiLatencies;
var
Ftdi: TSigFtdi;
cnt: DWORD;
i: Integer;
dev: ISigFtdiDeviceAccess;
PortName: string;
Latency: Integer;
begin
try
Ftdi := TSigFtdi.Create;
except
Ftdi := nil;
end;
try
if Assigned(Ftdi) then begin
cnt := Ftdi.GetDeviceCount;
for i := 0 to cnt - 1 do begin
if Ftdi.TryGetDevice(i, dev)
and dev.TryGetPortName(PortName)
and dev.TryGetPortLatency(Latency) then begin
if Latency > 4 then
Tf_dzDialog.ShowMessage(mtWarning,
Format(_('Latency timer of serial port %s is set to %d ms, should be <= 4 ms.'),
[PortName, Latency]), [dbeOK], Self);
end;
end;
end;
finally
dev := nil;
FreeAndNil(Ftdi);
end;
end;
procedure Tf_ArgVideoMainBase.CheckFtdiLatencies;
var
Ftdi: TSigFtdi;
cnt: DWORD;
i: Integer;
dev: ISigFtdiDeviceAccess;
PortName: string;
Latency: Integer;
begin
try
Ftdi := TSigFtdi.Create;
except
Ftdi := nil;
end;
try
if Assigned(Ftdi) then begin
cnt := Ftdi.GetDeviceCount;
for i := 0 to cnt - 1 do begin
if Ftdi.TryGetDevice(i, dev)
and dev.TryGetPortName(PortName)
and dev.TryGetPortLatency(Latency) then begin
if Latency > 4 then
Tf_dzDialog.ShowMessage(mtWarning,
Format(_('Latency timer of serial port %s is set to %d ms, should be <= 4 ms.'),
[PortName, Latency]), [dbeOK], Self);
end;
end;
end;
finally
dev := nil;
FreeAndNil(Ftdi);
end;
end;
I'm struggling to get past the swallow all exception handling
ReplyDeleteThomas Mueller - if TryGetDevice fails - the two following and parts will still execute - with an invalid dev. err... or not - if boolean shortcuts are enabled.
ReplyDeleteAre device indexes 0 to count-1 or 1 to count?
ReplyDelete...
ReplyDeletetry
Ftdi := TSigFtdi.Create;
except
...
Instantiation inside try...xxx block?!?
Lars Fosdal 0 to count-1
ReplyDeleteIggy White what's wrong with hat? It's a try except, not a try finally block.
ReplyDeletePlease note that I posted this in "Delphi Tips", not in "Delphi Help". I know the answer. I just thought it might be interesting for others to have a go at this. It took me only a few seconds to figure it out, but I had two unfair advantages: 1. I knew the code (don't remember if I wrote it or one of my colleagues) 2. I knew the error message.
ReplyDeleteHow does it fail?
ReplyDeletecnt: DWORD; //Unsigned 32bit
ReplyDeletefor i := 0 to cnt - 1 do begin //0 - 1 = 2^32
Thomas Mueller What's wrong with it is the fact that exceptions are swallowed
ReplyDeleteToo bad that with default settings, the compiler does not warn you about this.
ReplyDeleteSean Bogie No, its the loop variable's type that matters, it needs to be unsigned.
ReplyDeleteDavid Heffernan I'm not sure, whether changing the loop variable to DWord would solve the problem. Wouldn't that result in a loop 0 to 2^32-1 ?
ReplyDeleteLars Fosdal integer overflow due to cnt being 0.
ReplyDeleteI discovered this today because it was the first time the program ran on a computer without any ftdi USB to serial converters attached. Usually we have several, up to 5.
David Heffernan I could log the exceptions instead, but that wouldn't make a bit of a difference in this case. I simply don't care about any problems in TSigFtdi.Create. If it is serious, there will be more meaningful errors somewhere else.
ReplyDeleteThomas Mueller NO! I'm not proposing that. I'm saying that the loop variable needs to be signed. The code as it stands runs fine when cnt is zero. I guess if you have $Q+ then you might hit an exception. But otherwise that loop is fine.
ReplyDeleteSwallowing exceptions is usually bad. Your excuses don't convince me.
ReplyDeleteDavid Heffernan I'm fine with that (re disagreement on swallowing exceptions)
ReplyDeleteThomas Mueller I can see it's except not finally (and that nothing is wrong per se) but I never do it like this. Sorry if it offends you. :)
ReplyDeleteIf you don't care about exceptions there, don't handle them. Remove the try, remove the if Assigned.
ReplyDeleteThomas Mueller I work a lot with RS232.
ReplyDeleteInterested very much in what you did.
So where are those
TSigFtdi ISigFtdiDeviceAccess;
Where can i get the pas file to use those functions?
Are they part of which Delphi?
shlomo abuisak these are proprietary interfaces / units developed internally. "SIG" = "Schniering Ingenieur*g*esellschaft", the former name of my employer TÃœV Rheinland Schniering.
ReplyDeleteThey access the DLL that comes with the ftdi device drivers (don't remember the name) and also reads and writes to the associated registry entries.
Thomas Mueller thanks
ReplyDelete