List Info

Thread: Curious Bug in Delphi 5




Curious Bug in Delphi 5
country flaguser name
United States
2007-07-27 06:14:29

I've been writing a little test harness to test C and C++ dlls. It's for
this btw.
http://cplus.about.com/od/programmingchallenges/a/onchallenge1.htm

The Test harness for the C and C++ dlls was written in Delphi 5. It works ok
except it kept crashing quite badly when I called a function which passed
the address of a record in so the called function can access the record
data. I verified that the record structure size was identical in Delphi and
the dll.

The call worked fine, but when the delphi function which encapsulates the
call to the dll function exited, it bombed out. Ie I had done naughty things
to the stack. The calling convention was stdcall in the Delphi app, the
default (winapi in Microsoft parlance) in the C/C++ dll which equates to
stdcall on Windows XP.

I was doing this using loadlibrary btw. Ie select a dll, then use
GetProcAddress and call it.

type
TPlayerHistory = packed record // 104 bytes in size- same as in dll
MoveCount : integer;
Moves : array[1..100] of char;
end;
TmyfuncMove = function(var p : TPlayerHistory):integer;stdcall;

var
dllhandle : THandle;
pdllpathname : pchar;
dllpathname:string;
s : string;
fm : TMyFuncMove;
p : Pchar;
history : TPlayerHistory;
This is the function that bombs out.

function GetMove:string;
var b : byte; // <- fixes the bug, crashes if this unused variable is
removed!
begin
result :='Failed to locate entry point GetMove';
try
fm := GetProcAddress(dllhandle,'GetMove');
except
fm := nil;
end;
if not assigned(fm)then
exit
else
begin
try
result := Inttostr(fm(History)); // <- Calls the function here
except
on e:exception do
begin
ShowMessage(E.Message);
end;
end;
end;
end; // <- crashes here

It's called like this

procedure TForm1.btnStartClick(Sender: TObject);
var i : integer;
begin
dllhandle := 0;
try
pdllpathname := pchar(dllpathname);
dllhandle := LoadLibrary(pdllpathname);
fillchar(history.moves,sizeof(history.moves),' ');
for i:= 1 to 10 do
begin
History.MoveCount := i-1;
if i >1 then
History.Moves[i-1] := 'R';
ListBox1.Items.Add('Move '+ Inttostr(i)+' = '+ GetMove);
end;
finally
FreeLibrary( dllhandle );
end;
end;

I solved it and I think it is a bug in Delphi 5. If there is no local
variable declared in GetMove, I don't think it saves the stack correctly (I
had optimise turned off btw) and so crashes. It also crashes if optimization
is turned on, I presume because it zaps the local variable as it is unused.

At first I thought it was a calling convention mismatch but I proved that it
wasn't, by adding two dummy parameters and checking that it could still
access the History record in the dll.

So am I right that it is a bug or missing something else?

David Bolton

__________________________________________________________
The next generation of Hotmail is here! http://www.newhotmail.co.uk

__._,_.___
.

__,_._,___
Re: Curious Bug in Delphi 5
country flaguser name
Greece
2007-07-27 07:22:35
O/H David Bolton έγραψε:
> I've been writing a little test harness to test C and
C++ dlls. It's for 
> this btw.
> http://cplus.about.com/od/programmingchallenge
s/a/onchallenge1.htm
> 
> The Test harness for the C and C++ dlls was written in
Delphi 5. It works ok 
> except it kept crashing quite badly when I called a
function which passed 
> the address of a record in so the called function can
access the record 
> data. I verified that the record structure size was
identical in Delphi and 
> the dll.
> 
> The call worked fine, but when the delphi function
which encapsulates the 
> call to the dll function exited, it bombed out. Ie I
had done naughty things 
> to the stack. The calling convention was stdcall in the
Delphi app, the 
> default (winapi in Microsoft parlance) in the C/C++ dll
which equates to 
> stdcall on Windows XP.
> 
> I was doing this using loadlibrary btw. Ie select a
dll, then use 
> GetProcAddress and call it.
> 
> type
> TPlayerHistory = packed record // 104 bytes in size-
same as in dll
>   MoveCount : integer;
>   Moves     : array[1..100] of char;
> end;
> TmyfuncMove = function(var p :
TPlayerHistory):integer;stdcall;
> 
> var
> dllhandle : THandle;
> pdllpathname : pchar;
> dllpathname:string;
> s : string;
> fm : TMyFuncMove;
> p : Pchar;
> history : TPlayerHistory;
> This is the function that bombs out.
> 
> function GetMove:string;
> var b : byte;  // <- fixes the bug, crashes if this
unused variable is 
> removed!
> begin
>   result :='Failed to locate entry point GetMove';
>   try
>     fm := GetProcAddress(dllhandle,'GetMove');
>   except
>     fm := nil;
>   end;
>   if not assigned(fm)then
>     exit
>   else
>      begin
>        try
>           result := Inttostr(fm(History));  // <-
Calls the function here
>        except
>          on e:exception do
>            begin
>              ShowMessage(E.Message);
>            end;
>          end;
>      end;
> end;  // <- crashes here
> 
> It's called like this
> 
> procedure TForm1.btnStartClick(Sender: TObject);
> var i : integer;
> begin
>   dllhandle := 0;
>   try
>     pdllpathname := pchar(dllpathname);
>     dllhandle := LoadLibrary(pdllpathname);
>     fillchar(history.moves,sizeof(history.moves),' ');
>     for i:= 1 to 10 do
>       begin
>         History.MoveCount := i-1;
>         if i >1 then
>           History.Moves[i-1] := 'R';
>         ListBox1.Items.Add('Move '+ Inttostr(i)+' = '+
GetMove);
>       end;
>   finally
>     FreeLibrary( dllhandle );
>   end;
> end;
> 
> I solved it and I think it is a bug in Delphi 5. If
there is no local 
> variable declared in GetMove, I don't think it saves
the stack correctly (I 
> had optimise turned off btw) and so crashes. It also
crashes if optimization 
> is turned on, I presume because it zaps the local
variable as it is unused.
> 
> At first I thought it was a calling convention mismatch
but I proved that it 
> wasn't, by adding two dummy parameters and checking
that it could still 
> access the History record in the dll.
> 
> So am I right that it is a bug or missing something
else?
> 
> David Bolton


Hi David

try changing

 > TPlayerHistory = packed record // 104 bytes in size-
same as in dll
 >   MoveCount : integer;
 >   Moves     : array[1..100] of char;
 > end;

into

   TPlayerHistory = packed record
     MoveCount : Integer;
     Moves     : array[0..99] of Char;
   end;

and ommit the b local variable to see if it works.

BTW, what the C dll does with the Moves field? And how
access it?
As a zero terminated C/C++ string?


-- 
Regards
Theo

------------------------
Theo Bebekis
Thessaloniki, Greece
------------------------
Greek_Delphi_Prog : a Delphi Programming mailing list in
Greek at
    http:
//groups.yahoo.com/group/Greek_Delphi_Prog

CSharpDotNetGreek : A C# and .Net mailing list in Greek
language at
    http:
//groups.yahoo.com/group/CSharpDotNetGreek

atla_custom : a Unisoft Atlantis Customization mailing list
at
    http://grou
ps.yahoo.com/group/atla_custom
------------------------


-----------------------------------------------------
Home page: http://group
s.yahoo.com/group/delphi-en/
To unsubscribe: delphi-en-unsubscribe@yahoogroups.com 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://group
s.yahoo.com/group/delphi-en/

<*> Your email settings:
    Individual Email | Traditional

<*> To change settings online go to:
    http://g
roups.yahoo.com/group/delphi-en/join
    (Yahoo! ID required)

<*> To change settings via email:
    mailto:delphi-en-digest@yahoogroups.com 
    mailto:delphi-en-fullfeatured@yahoogroups.com

<*> To unsubscribe from this group, send an email to:
    delphi-en-unsubscribe@yahoogroups.com

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.c
om/info/terms/
 

[1-2]

about | contact  Other archives ( Real Estate discussion Medical topics )