Hello Martin,

I meant "when you pass a va_list to a function, it is assumed that it will
be 'consumed' by the called function". So, as I use two functions, the
params is freed by the first one.

Consider the following MHD log error:

'Failed to bind to port 8080: Address already in use'#10 // #10 is similar
to \n

If you try:

function _vscprintf(format: pcchar; ap: va_list): cint; cdecl;
begin
  Result := vsnprintf(nil, 0, format, ap);
end;

...

var
  VLength: Integer;
  VBuffer: AnsiString;
begin
  VLength := _vscprintf(AFmt, AArgs); // AArgs is my "va_list", and the
_vscprintf() frees it here
  SetLength(VBuffer, VLength);
  VLength := vsnprintf(@VBuffer[1], VLength, AFmt, AArgs); // AArgs was
freed by _vscprintf
  SetLength(VBuffer, VLength);
  WriteLn(VBuffer);
end;

It prints:

'Failed to bind to port 4278124287: (null)'#10

Because the params was freed. Pascal doesn't have the C++ va_copy function,
so I can't use a tip like this:

http://stackoverflow.com/questions/4785381/replacement-for-ms-vscprintf-on-macos-linux

But I'm also not sure about passing the NULL to the vsnprintf, so I choose
a known approach, that's fill a dynamic array:

var
  VLength: Integer;
  VResult: RawByteString;
  VBuffer: array[0..1024] of AnsiChar; // as Christian said, 1024 sounds a
good size
begin
  VLength := vsnprintf(VBuffer, Length(VBuffer), AFmt, AArgs); // Pascal
already declare the "vsnprintf(VBuffer" as "vsnprintf(@VBuffer[1]"
  SetString(VResult, PAnsiChar(VBuffer), VLength);
  SetCodePage(VResult, CP_UTF8, False);
  WriteLn(VResult); // I need the end string as UTF-8 string
end;

And finally I got the correct buffer.

But it was just for fix my code on Linux, on Windows I use the _vscprintf()
function, but if in the future I could find some function like va_copy()
for Pascal, I can easily update my code to use that. :-)

On Tue, Mar 1, 2016 at 4:57 AM, Martin Bonner <[email protected]>
wrote:

> Silvio:  What do you mean by „I can’t use vsnprintf(NULL, 0, fmt, args) on
> Pascal because it frees the arguments”?  What frees what arguments?
>
Would it help to use “char buffer[1]; vsnprintf(buffer, sizeof(buffer),
> fmt, args)”?  (It still ought to return the total size you need).  I’m not
> sure that passing NULL as the buffer is legal (even when the count is zero).
>
>
>
> Also beware: I have a feeling that Visual Studio 2015 handles vsnprintf
> correctly for
>
> overflow (in that it always nul-terminates), but earlier versions do not.
> Of course, if you are going to go round again and just allocate a large
> enough buffer, that doesn’t matter.
>

-- 
Silvio Clécio

Reply via email to