Когда container_append
называется так
container_append(c, NULL);
именованный параметр element
будет равен 0, и анонимных параметров не будет. При этих условиях container_append
вообще не должен вызывать va_arg
, иначе программа имеет неопределенное поведение. Это случилось случайно до того, как вы реорганизовали код, но исходный код так же глючит, как и реорганизованная версия.
Вы можете либо проверить element
перед циклом ...
void
container_append(container_t *c, element_t *element, ...)
{
if (!element) return;
container_append_aux(c, element);
va_list ap;
va_start(ap, element);
while ((element = va_arg(ap, element_t *)))
container_append_aux(c, element);
va_end(ap);
}
... или вы можете сделать все аргументы элемента анонимными:
void
container_append(container_t *c, ...)
{
va_list ap;
va_start(ap, c);
element_t *e;
while ((e = va_arg(ap, element_t *)))
container_append_aux(c, e);
va_end(ap);
}
Последняя структура более совместима с рефактором vappend
, который вы хотите использовать.
РЕДАКТИРОВАТЬ: Относительно этого запроса в комментарии:
Я думал, va_start(ap, element)
(в вызывающей программе) настроит va_arg для возврата элемента первым. Может быть, это так не работает?
Действительно, это не работает таким образом. va_start
устанавливает va_arg
для возврата первого из анонимных аргументов. Если не было никаких анонимных аргументов, то вы выходите из конца при первом вызове va_arg
и запускаете UB.