GCC неправильно обрабатывает указатель на va_list, переданный функции?

Вопрос ' Передайте va_list или указатель to va_list? ' содержит ответ, в котором цитируется стандарт (ISO / IEC 9899: 1999 - §7.15' Переменные аргументы , сноска 212), в котором прямо говорится, что:

Разрешается создать указатель на va_list и передать этот указатель другой функции, и в этом случае исходная функция может в дальнейшем использовать исходный список после возврата из другой функции.

Я компилирую код, который можно проиллюстрировать следующим (реальный код намного сложнее, а исходные функции выполняют гораздо больше работы, чем показано здесь).

vap.c

#include 
#include 

static void test_ptr(const char *fmt, va_list *argp)
{
    int x;
    x = va_arg(*argp, int);
    printf(fmt, x);
}

static void test_val(const char *fmt, va_list args)
{
    test_ptr(fmt, &args);
}

static void test(const char *fmt, ...)
{
    va_list args;
    va_start(args, fmt);   /* First use */
    test_val(fmt, args);
    va_end(args);
    va_start(args, fmt);   /* Second use */
    test_ptr(fmt, &args);
    va_end(args);
}

int main(void)
{
    test("%d", 3);
    return 0;
}

Сообщения об ошибках

Когда я компилирую его (на RHEL5 с GCC 4.1.2 или 4.5.1), я получаю следующие сообщения об ошибках. Обратите внимание, насколько информативнее сообщение об ошибке 4.5.1 - команду GCC следует поздравить с улучшением!

$ gcc --version
gcc (GCC) 4.5.1
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ /usr/bin/gcc --version
gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-44)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ gcc -c vap.c
vap.c: In function ‘test_val’:
vap.c:13:5: warning: passing argument 2 of ‘test_ptr’ from incompatible pointer type
vap.c:4:13: note: expected ‘struct __va_list_tag (*)[1]’ but argument is of type ‘struct __va_list_tag **’
$ /usr/bin/gcc -c vap.c
vap.c: In function ‘test_val’:
vap.c:13: warning: passing argument 2 of ‘test_ptr’ from incompatible pointer type
$ 

Я получаю те же сообщения на MacOS X Lion с GCC / LLVM 4.2.1 и с GCC 4.6.1:

$ /usr/bin/gcc --version
i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ gcc --version
gcc (GCC) 4.6.1
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$

Вопросы

  • Может ли кто-нибудь сформулировать, почему функция test_val () не может передать va_list , переданный в качестве аргумента test_ptr () , тогда как функция test () (которая создала va_list ) может?

  • Правильно ли GCC жаловаться на косвенную передачу указателя в test_val () ?

В обоих случаях я нечетко вижу ответ, но не могу описать его кратко. Я думаю, что код в test_val () злоупотребляет va_list , и это хорошо, что код не компилируется, но я хотел бы убедиться, прежде чем исправлять его .


Обновление 30.03.2012

На этой неделе я решил разобраться с проблемным кодом. Прежде чем вносить изменения, я попытался найти, где используются злоумышленники - а это не так! Итак, я решил проблему с ошибкой компиляции, удалив функции (4 внешне видимых, но неиспользуемых, плюс 2 статические, содержащие проблемный код). Это было намного проще, чем думать, как разобраться с беспорядком. (Это также объясняет, почему никогда не было никаких доказательств проблемы во время выполнения, вызванной кодом.)

25
задан Community 23 May 2017 в 12:02
поделиться