------- Comment #21 from rogerio at rilhas dot com  2010-08-11 17:04 -------
Subject: Re:  Indirect variable parameters sometimes cause
 segmentation fault

Yes, I was using that solution up to 2003, but then I stopped
using it in favour of the more confortable &format (the one I
showed you) because it is less error-prone and easier to automate
(no need for the va_list declaration, start, and end). My teams
usually have a lot of rookies (we have schollarship programs)
and bugs would popup a lot (like switching the order of
parameters, for example).

I could go back to using it, of course, but I already have a lot
of code done with this &format method, and it is not convenient
for me to go back and change anything in old code.

Anyway, I seem to have found a workaround for this problem
in GCC: it seems that if I use the &format before calling the
format_indirect then there will be no problem (still to conform).

void format_direct(char* dst_buffer, int dst_buffer_size_bytes, const 
char* format, ...) {
    const char** format_address=&format;
    format_indirect(dst_buffer, dst_buffer_size_bytes, format_address);
}

If I confirm this then this problem would no longer be blocking
and I would be able to live with it by creating a special macro
in Linux to use the &format before calling format_indirect:

#define GCC_SPECIFIC_ADDRESS_OF(format) const char** format_address(&format)

void format_direct(char* dst_buffer, int dst_buffer_size_bytes, const 
char* format, ...) {
    format_indirect(dst_buffer, dst_buffer_size_bytes, 
GCC_SPECIFIC_ADDRESS_OF(format));
}

... or something along these lines. Maybe I should also replace const
char** by some other GCC-specificy defined type (that would have
no effect on Windows) just to get compilation errors where people try
to pass &format directly whitout using the macro.

matz at gcc dot gnu dot org wrote:
> ------- Comment #20 from matz at gcc dot gnu dot org  2010-08-11 16:10 -------
> A conforming variant of what you probably are trying to code is:
> --------------------------------------------------------------------
> #include <stdio.h>
> #include <stdarg.h>
>
> void format_indirect(char* dst_buffer, size_t dst_buffer_size_bytes,
>                      const char *format, va_list va)
> {
>     vsnprintf(dst_buffer, dst_buffer_size_bytes, format, va);
>     dst_buffer[dst_buffer_size_bytes-1]=0;
> }
>
> void format_direct(char* dst_buffer, size_t dst_buffer_size_bytes,
>                    const char* format, ...)
> {
>     va_list va;
>     va_start (va, format);
>     format_indirect(dst_buffer, dst_buffer_size_bytes, format, va);
>     va_end (va);
> }
>
> int main(void)
> {
>     char buffer[1000];
>     format_direct((char*)buffer, sizeof(buffer), "%s %s", __DATE__, __TIME__);
>     printf("Result: \"%s\"\n", buffer);
>     return 0;
> }
> -----------------------------------------------------------
>
> Note how the va_list is constructed in the function that actually is
> a varargs one, in particular how the necessary parameter is mentioned.
> Note further how that va_list is passsed to the function that is not
> varargs in order to capture all variable arguments of its caller.
>
> There, no assumption on stack-layout.  It will work with all types and
> ABIs, even those that happen to pass even some varargs in registers,
> not on the stack.
>
>
>   


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249

Reply via email to