'Variadic arguments bug Macbook Air M1
I'm currently creating a printf function from scratch which is working on a iMac 2020 and not on Air M1
If I try to test with the same % and different results, it will always show the first one.
For example: ft_printf(“test %s %s”, “test2", “test3”) Output: test test2 test2
But the output on the iMac is the correct one: test test2 test3
this is the main function:
int main()
{
ft_printf("test %s %s\n", "test2", "test3");
printf("test %s %s\n", "test2", "test3");
return (0);
}
int ft_printf(const char *str, ...)
{
va_list ap;
int cont;
int ret;
cont = 0;
va_start(ap, str);
while (str[cont] != '\0')
{
if (str[cont] == '%')
{
ft_after_percentage(ap, str[cont + 1]);
cont += 2;
continue ;
}
write(1, &str[cont], 1);
ft_count_return(0);
cont++;
}
va_end(ap);
ret = ft_count_return(0) - 1;
ft_count_return(1);
return (ret);
}
void ft_after_percentage(va_list ap, char c)
{
if (c == 'c')
ft_putchar(va_arg(ap, int));
else if (c == 's')
ft_putstr(va_arg(ap, char *));
else if (c == 'p')
ft_percentage_p(va_arg(ap, long unsigned));
else if (c == 'd')
ft_putnbr(va_arg(ap, int));
else if (c == 'i')
ft_putnbr(va_arg(ap, int));
else if (c == 'u')
ft_uns_putnbr(va_arg(ap, unsigned int));
else if (c == 'x')
ft_puthex(va_arg(ap, int), "0123456789abcdef");
else if (c == 'X')
ft_puthex(va_arg(ap, int), "0123456789ABCDEF");
else if (c == '%')
ft_putchar('%');
}
Solution 1:[1]
Once you have passed the va_list variable by value to another function which uses va_arg() on it, you are not supposed to use that va_list variable in the calling function again.
The C99 standard, in the section for the stdarg.h header, says:
The type declared is
va_listwhich is an object type suitable for holding information needed by the macrosva_start,va_arg,va_end, andva_copy. If access to the varying arguments is desired, the called function shall declare an object (generally referred to asapin this subclause) having typeva_list. The objectapmay be passed as an argument to another function; if that function invokes theva_argmacro with parameterap, the value ofapin the calling function is indeterminate and shall be passed to theva_endmacro prior to any further reference toap.212)
So here, you pass ap by value to ft_after_percentage(), which calls va_arg() on it, and then you continue to use ap in the calling function (by passing it to ft_after_percentage() for the second variable argument). This causes undefined behavior. It might happen to work on one architecture, but not another, due to differences in how va_list is implemented between architectures.
The footnote from above suggests for your ft_after_percentage() to instead take a va_list *, and pass &ap to it:
: 212) It is permitted to create a pointer to a
va_listand pass that pointer to another function, in which case the original function may make further use of the original list after the other function returns.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | newacct |
