Page 1 of 1

Proto without proper params

Posted: Fri May 16, 2025 10:49 am
by Joubarbe

Code: Select all

Prototype __Generic(custom_value)

Structure _var
  *callback.__Generic
EndStructure

Procedure Func() ; We omit custom_value for the sake of the demonstration.
  Debug "Func() called"
EndProcedure

Procedure AddCallback(*var._var, *callback.__Generic)
  *var\callback = *callback
EndProcedure

Procedure CallCallback(*var._var, custom_value)
  *var\callback(custom_value)
EndProcedure

Define var._var

AddCallback(@var, @Func())
CallCallback(@var, 0)
I often do this kind of code for various reasons, and I use the __Generic prototype without argument. Considering that Func() is NOT complying with the prototype definition, I'd like to know if there's any chance of a memory leak or any undefined behaviour? In other words, is it a problem?

Re: Proto without proper params

Posted: Fri May 16, 2025 11:59 am
by NicTheQuick
I am not an expert in this but I think on 64 bit platforms that one parameter should not be an issue because parameters are usually passed through registers. On 32 bit platforms parameters will be pushed on the stack before calling a function and there you can run into huge problems because the stack is no longer properly aligned.

Anyway, I might be wrong here and I am sure other members are more experienced in stuff like that.

Re: Proto without proper params

Posted: Fri May 16, 2025 1:51 pm
by SMaag
I go conforme with NichTheQuick!

A short time ago there was a similar problem on the forum, where such a construction caused a problem (but wiht more parameters).
By any reason PB do not check the correctnes of the Parameter.
I remember there was a comment from Fred. But I can't remember it.

C x32, x64
I guess it works in C-Backend. I guess C will use EAX, EDX for the first 2 parameters.

ASM x32, x64
I guess it will work because PB moves anything to the Stack!

here the x64 ASM Output

Code: Select all

; Procedure CallCallback(*var._var, custom_value)
_Procedure6:
  MOV    qword [rsp+8],rcx		; looks  like 1st Parameter to var on Stack
  MOV    qword [rsp+16],rdx               , looks like 2nd Paramenter to var on Stack
  PUSH   rbp
  PS6=64
  XOR    rax,rax					; RAX = 0
  PUSH   rax						; 0 to Stack - looks like the custom_value
  SUB    rsp,40
; *var\callback(custom_value)        ; prepare for Call the Callback
  MOV    rbp,qword [rsp+PS6+0]
  PUSH   qword [rbp]
  SUB    rsp,8
  PUSH   qword [rsp+PS6+24]
  POP    rcx
  SUB    rsp,32
  CALL   qword [rsp+40]
  ADD    rsp,40
  ADD    rsp,8
; EndProcedure


Re: Proto without proper params

Posted: Fri May 16, 2025 3:09 pm
by Joubarbe
Interesting...

@Fred: would it not be possible to add a check when passing a non-conform function address as callback (like @Func() in my example)?

Re: Proto without proper params

Posted: Fri May 16, 2025 7:35 pm
by wilbert
Joubarbe wrote: Fri May 16, 2025 10:49 am In other words, is it a problem?
Yes, it's a problem (on Windows x86).

There are different calling conventions for different systems and processors.
On Windows x86 the default calling convention (stdcall) requires the callee to clean up the stack. In this case it's important the amount of procedure arguments match.
When using the C calling convention (cdecl) on Windows x86, the caller is responsible for cleaning up the stack so in that case there is no problem if more arguments are passed as the callee expects.

To fix the problem with your code you can use the C convention like this

Code: Select all

PrototypeC __Generic(custom_value)

Structure _var
  *callback.__Generic
EndStructure

ProcedureC Func() ; We omit custom_value for the sake of the demonstration.
  Debug "Func() called"
EndProcedure

Procedure AddCallback(*var._var, *callback.__Generic)
  *var\callback = *callback
EndProcedure

Procedure CallCallback(*var._var, custom_value)
  *var\callback(custom_value)
EndProcedure

Define var._var

AddCallback(@var, @Func())
CallCallback(@var, 0)

Re: Proto without proper params

Posted: Fri May 16, 2025 10:03 pm
by Joubarbe
Thank you wilbert for the explanation. I'll try declaring proper functions from now on :D But I always compile in x64, so if I understand you correctly, it shouldn't cause any problem (still going to do proper declarations for sure).

Re: Proto without proper params

Posted: Sat May 17, 2025 5:28 am
by wilbert
Joubarbe wrote: Fri May 16, 2025 10:03 pm But I always compile in x64, so if I understand you correctly, it shouldn't cause any problem (still going to do proper declarations for sure).
When using 64 bit, most procedure arguments are passed by registers but even if the stack is used, the 64 bit calling conventions require the caller to do the stack cleanup (on Windows, macOS and Linux, both x64 and ARM64).
So if you always compile for 64 bit there shouldn't be a problem.

Re: Proto without proper params

Posted: Sat May 17, 2025 8:37 am
by Joubarbe
Would that be possible to implement a compiler check on @Func() when calling AddCallback()?
In CallCallback(), *var\callback()'s arity is checked, so maybe it's doable...? Or maybe it would be too much of a change for existing programs?