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

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?