Странность с va_copy
Dec. 9th, 2018 09:28 pm![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Вот такую странную картину я тут наблюдаю:
Debian testing, gcc 8.2.0. Имеется вот такой C-шный код:
В 64-битной системе компилятор кушает этот код без вопросов. В 32-битной ругается
error: ‘std_args’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
vfprintf(stderr, fmt, std_args);
Нет, я понимаю, что макросы для va_* могут быть реализованы по разному в зависимости от архитектуры процессора, но не до такой же степени...
Debian testing, gcc 8.2.0. Имеется вот такой C-шный код:
static void log (int elevel, const char *fmt, va_list args) { bool write_to_file, write_to_stderr, write_somewhere_else; va_list error_args, std_args; .... здесь вычисляем куда надо писать if (write_to_file && write_to_stderr) va_copy(std_args,args); .... некоторое количество кода, заведомо не меняющего флагов write_to if (write_to_file) { vfprintf(f,fmt, args); } if (write_to_stderr) { if (write_to_file) { vfprintf(stderr, fmt, std_args); } else { vfprintf(stderr,fmt,args); } ffush(stderr); }
В 64-битной системе компилятор кушает этот код без вопросов. В 32-битной ругается
error: ‘std_args’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
vfprintf(stderr, fmt, std_args);
Нет, я понимаю, что макросы для va_* могут быть реализованы по разному в зависимости от архитектуры процессора, но не до такой же степени...
no subject
Date: 2018-12-09 06:59 pm (UTC)эквивалентно условию
А это, кроме всего прочего, ещё и другой порядок аргументов в короткой конъюнкции.
no subject
Date: 2018-12-09 07:28 pm (UTC)А у меня их там мно-о-ого - от GCC 4.3.4 в SUSE 11 до этого самого 8.2 и еще некоторое количество CLANG-ов.
no subject
Date: 2018-12-09 07:35 pm (UTC)va_copy
? Ну, допустим, в какой-то архитектуре повезло, и это явное копирование. Но я бы на всякий случай предполагал, что это, как и в большинстве Си-шных конструкци такого рода, - просто вызов некой функции, которой передают указатели на оба аргумента. Однако, передача в какую-то функцию указателя на локальную переменную - ещё не повод считать эту переменную инициализированной.no subject
Date: 2018-12-10 08:37 am (UTC)А по хорошему счету, он обязан это знать и про все функции стандартной библиотеки (хотя, возможно это уже обязанность авторов стандартной библиотеки - пометить соответствующие аргументы соответствующим __attribute__).
Вообще, gcc в режиме проверок умеет много разных гитик. Например умеет понимать конструкцию вида
no subject
Date: 2018-12-10 08:44 am (UTC)Но по-хорошему, конечно, надо там вместо брейка ставить какую-то конструкцию, однозначно понимаемую и человеком, и компилятором, что брейк здесь пропущен умышленно. Вроде, в C# так и сделали.
no subject
Date: 2018-12-10 09:03 am (UTC)no subject
Date: 2018-12-10 09:05 am (UTC)no subject
Date: 2018-12-10 05:22 am (UTC)no subject
Date: 2018-12-10 08:33 am (UTC)no subject
Date: 2018-12-10 08:40 am (UTC)А бывают ещё случаи, когда переменная заведомо неинициализированная.
no subject
Date: 2018-12-10 09:04 am (UTC)no subject
Date: 2018-12-10 09:19 am (UTC)no subject
Date: 2018-12-10 08:31 pm (UTC)no subject
Date: 2018-12-10 07:09 am (UTC)У меня было как-то ещё в эпоху PDP-11 и "Ленинградского Си" анекдотическое.
if (условие) функция();
компилировалось в какой-то махровый бред, ибо функция была на самом деле чуть криво написанным макросом, результат раскрытия которого частично "выпадал" из блока условия.
if (условие) { функция(); }
компилировалось как ожидалось и работало правильно.
no subject
Date: 2018-12-10 07:24 am (UTC)no subject
Date: 2018-12-10 08:22 am (UTC)А vfprintf вообще не макрос.
Еще интереснее - результат препроцессирования данной функции в 32-битной среде (где ругается) и в 64-битной) вообще никак не различается.
no subject
Date: 2018-12-10 09:04 am (UTC)no subject
Date: 2018-12-10 09:19 am (UTC)И макрос не такой уж развесистый.
no subject
Date: 2018-12-10 10:14 am (UTC)К счастью, конфликтов, когда в одних контекстах надо бы окружать фигурными скобками, а в других - круглыми, в Си не бывает. По крайней мере, я таких примеров не встречал.
no subject
Date: 2018-12-10 10:16 am (UTC)no subject
Date: 2018-12-10 10:19 am (UTC)Ну и вообще врождённых болезней у языка препроцессора много :)
no subject
Date: 2018-12-10 10:54 am (UTC)Ну каноническое решение против else выглядит как
no subject
Date: 2018-12-10 11:01 am (UTC)no subject
Date: 2018-12-10 11:06 am (UTC)no subject
Date: 2018-12-11 02:35 am (UTC)no subject
Date: 2018-12-10 07:16 am (UTC)Примерно как в Турбо Си 2.0 было две хорошо применяемых модели памяти - Tiny и Huge.
в первой указатели были 16-битные, и результат собирался в .com файл.
во второй указатели были кривые интеловские, но арифметика их РАБОТАЛА КОРРЕКТНО.
Попытки компилить РАБОТАЮЩИЙ в Tiny и Huge код в прочих моделях памяти (Small и Large) рано или поздно приводили к сегфолтам и к иным странным результатам.
no subject
Date: 2018-12-10 07:22 am (UTC)Можно, конечно, залезть в определения макросов va_copy. Но лучше я это на авторов этого кода свалю.
У меня еще дохренадцать warning-ов в 12 ветках есть. (этот, правда, есть в 10 из 12).