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
