Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2016-01

SIGSEGV when using varargs calling

9 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

silvioprog

Hello,

Consider the following types:

  TPuts1 = procedure; cdecl varargs;
  TPuts2 = procedure(par: string); cdecl varargs;
  TPuts3 = procedure(const par: string); cdecl varargs;

this procedure:

  procedure Puts(par1, par2, par3: string); cdecl;
  begin
    Write(par1, ' ');
    Write(par2, ' ');
    Write(par3, ' ');
    Writeln('');
  end;

and this callings:

var
  PutsX: Pointer;
begin
  TPuts1(@Puts)('Hello1', 'World1', 'HogeMoge1');
  TPuts2(@Puts)('Hello2', 'World2', 'HogeMoge2');
  TPuts3(@Puts)('Hello3', 'World3', 'HogeMoge3');
  PutsX := @Puts;
  TPuts1(PutsX)('Hello4', 'World4', 'HogeMoge4');
  TPuts2(PutsX)('Hello5', 'World5', 'HogeMoge5');
  TPuts2(PutsX)('Hello6', 'World6', 'HogeMoge6');
  Readln;
end.

It compiles fine on Delphi, but in FPC I got the following error:

'Wrong number of parameters specified for call to "<Procedure Variable>"'.

OK, I just commented the wrong lines to be able to compile that:

begin
//  TPuts1(@Puts)('Hello1', 'World1', 'HogeMoge1');
  TPuts2(@Puts)('Hello2', 'World2', 'HogeMoge2');
  TPuts3(@Puts)('Hello3', 'World3', 'HogeMoge3');
  PutsX := @Puts;
//  TPuts1(PutsX)('Hello4', 'World4', 'HogeMoge4');
  TPuts2(PutsX)('Hello5', 'World5', 'HogeMoge5');
  TPuts2(PutsX)('Hello6', 'World6', 'HogeMoge6');
  Readln;
end.

But, after compile it in FPC and run the program, I got a SIGSEGV with the following stack trace (compiled on Delphi it runs properly):

#0 SYSTEM_$$_SPTR$$POINTER at :0
#1 fpc_ansistr_incr_ref at :0
#2 PUTS(<error reading variable>, <error reading variable>, <error reading variable>) at project1.lpr:14
#3 :25

However, if you declare it using integers, it compiles and works fine in both compilers:

  TPuts = procedure(p0: Integer); cdecl varargs;
  procedure Puts(p1, p2, p3: Integer); cdecl;
  begin
    WriteLn(p1, p2, p3);
  end;
begin
  TPuts(@Puts)(1, 2, 3);

Below the generated asm to check why the first calling doesn't work in FPC if the params was declared as strings:

{$IFDEF FPC}
  {$MODE DELPHI}
{$ENDIF}
  TPuts = procedure(const p0: string); cdecl varargs;
  procedure Puts(const p1, p2, p3: string); cdecl;
  begin
    WriteLn(p1, p2, p3);
  end;
begin
  TPuts(@Puts)('1', '2', '3');

[FPC]

project1.lpr:17 TPuts(@Puts)('1', '2', '3');
004015B9 6a33 push $0x33
004015BB 6a32 push $0x32
004015BD b810b04000 mov $0x40b010,%eax 004015C2 50 push %eax
004015C3 b850154000 mov $0x401550,%eax 004015C8 ffd0 call *%eax
004015CA 83c40c add $0xc,%esp

[/FPC]

[DELPHI]

Project1.dpr.17: TPuts(@Puts)('1', '2', '3');
004060D4 6A33 push $33
004060D6 6A32 push $32
004060D8 6808614000 push $00406108
004060DD B86C5B4000 mov eax,$00405b6c
004060E2 FFD0 call eax
004060E4 83C40C add esp,$0c

[/DELPHI]

What I'm doing wrong? Can I use this callings on FPC in the DELPHI mode?! :-/

Silvio Clécio
Sven Barth
to silvioprog
"silvioprog" wrote
What I'm doing wrong? Can I use this callings on FPC in the DELPHI mode?!

:-/

Neither FPC nor Delphi allow you to declare your own varargs functions. That it works in Delphi is by pure change. Trying to outsmart the compiler will only lead to trouble.

Regards,
Sven

leledumbo
to Sven Barth
Neither FPC nor Delphi allow you to declare your own varargs functions.

That it works in Delphi is by pure change. Trying to outsmart the compiler will only lead to trouble.

AFAIR it was supported until certain FPC version, but the dropped entirely to only for external C functions.
The related error message (search for "varargs" here: http://www.freepascal.org/docs-html/user/userse62.html) explains it (better than the documentation page for varargs directive: http://www.freepascal.org/docs-html/ref/refsu88.html)

View this message in context: http://free-pascal-general.1045716.n5.nabble.com/SIGSEGV-when-using-varargs-calling-tp5723661p5723669.html Sent from the Free Pascal - General mailing list .
Jonas Maebe
to Sven Barth: :-/ Neither FPC nor Delphi allow you to declare your own varargs functions. That it works…
Sven Barth wrote 7 lines
Am 25.01.2016 04:42 schrieb "silvioprog" < >: > What I'm doing wrong? Can I use this callings on FPC in the DELPHI mode?! :-/ Neither FPC nor Delphi allow you to declare your own varargs functions. That it works in Delphi is by pure change.

It will also only work on certain platforms with Delphi, or even in C. E.g. on iOS/AArch64, varargs parameters are almost always passed differently compared to regular parameters.

Jonas

Jonas Maebe
to leledumbo: Found it: http://wiki.lazarus.freepascal.org/User_Changes_2.6.0#Array_of_const_parameters_…
leledumbo wrote

As that entry notes, it was not supported: "There is however no way in (Free) Pascal to access these arguments on the callee side". This includes the case where you try to hack around this by declaring fake parameters, such as what Silvio was doing.

The compiler didn't throw an error, but that's similar to how it didn't throw an error in case of e.g.
http://wiki.freepascal.org/User_Changes_3.0#Classes_implementing_forward-declared_interfaces

Jonas

silvioprog
to Sven Barth: :-/ Neither FPC nor Delphi allow you to declare your own varargs functions. That it works…
Sven Barth wrote 8 lines
Am 25.01.2016 04:42 schrieb "silvioprog" : > What I'm doing wrong? Can I use this callings on FPC in the DELPHI mode?! :-/ Neither FPC nor Delphi allow you to declare your own varargs functions. That it works in Delphi is by pure change. Trying to outsmart the compiler will only lead to trouble.

Indeed [1]. I found some Delphi programmers using this (wrong) calling, eg[2][3]. :-/

[1]
http://docwiki.embarcadero.com/RADStudio/Seattle/en/E2277_Only_external_cdecl_functions_may_use_varargs_(Delphi) [2] http://www.swissdelphicenter.ch/torry/showcode.php?id=2114 [3]
http://tobysoft.net/wiki/index.php?Delphi%2F%B2%C4%CA%D1%C4%B9%B0%FA%BF%F4%A1%CAvarargs%A1%CB

Silvio Clécio
silvioprog
to leledumbo: That it works in Delphi is by pure change. Trying to outsmart the compiler will only lead…
leledumbo wrote 11 lines
> Neither FPC nor Delphi allow you to declare your own varargs functions. That it works in Delphi is by pure change. Trying to outsmart the compiler will only lead to trouble. AFAIR it was supported until certain FPC version, but the dropped entirely to only for external C functions. The related error message (search for "varargs" here: http://www.freepascal.org/docs-html/user/userse62.html) explains it (better than the documentation page for varargs directive: http://www.freepascal.org/docs-html/ref/refsu88.html)

Thanks for sharing the links.

Silvio Clécio
silvioprog
to leledumbo: Found it: http://wiki.lazarus.freepascal.org/User_Changes_2.6.0#Array_of_const_parameters_…
leledumbo wrote 5 lines

Thanks for the link. I didn't see this Remedy: "Remove the cdecl specifier and use a Pascal-style array of const, or implement the routine in C and add external to the Pascal declaration.".

Silvio Clécio