Вышел корректирующий релиз набора компиляторов GCC 4.5.2 (http://gcc.gnu.org/), в котором проведена работа по исправлению ошибок, регрессивных изменений и проблем с совместимостью. С момента выхода прошлой версии отмечено (http://gcc.gnu.org/bugzilla/buglist.cgi?bug_status=RESOLVED&...) 75 исправлений, большинство из которых связанно с устранением внесенных ранее регрессивных изменений. Исходные тексты компилятора можно загрузить с сайта проекта (ftp://gcc.gnu.org/pub/gcc/releases/gcc-4.5.2/) или с его зеркал (http://gcc.gnu.org/mirrors.html).URL: http://gcc.gnu.org/
Новость: http://www.opennet.me/opennews/art.shtml?num=29031
во. интересно, avr-g++ пофиксили?
Он никогда и не ломался.
4.5.1 сегфолтится на моем "изобретении". багрепорт решил не писать до обновления. Вот до арча 4.5.2 доползет - попробую...
> 4.5.1 сегфолтится на моем "изобретении". багрепорт решил не писать до обновления. Вот до арча 4.5.2 доползет - попробую...Ага, жди у моря погоды.
gcc уже научился компилить _работающий_ код следующего примера,
ну или не компилить, хотя бы с warning'ом, хотя бы при -pedantic -Wall$cat x.c
struct A
{
int k;
};int foo(struct A *a)
{
{
struct A *a = a;
return a->k;
}
}int main(int argc, char *argv[])
{
struct A s = {111};
return foo(&s);
}$gcc -Wall -pedantic x.c; ./a.out; echo $?
72$gcc -Wall -pedantic -O2 x.c; ./a.out; echo $?
SIGSEGV
А то страшно писать код с макросами вида#define DUMP(x) \
do { \
struct A *a = x; \
printf("%d,%d\n", a->k1, a->k2); \
} while (0)
потому что при вызовеDUMP(a);
программа падает по SIGSEGV.
> struct A *a = a;Поздравляю, вы выиграли медаль «Гений программирования».
>> struct A *a = a;
> Поздравляю, вы выиграли медаль «Гений программирования».Чуть-чуть сильнее напрягите извилины.
Это сейчас очевидно где ошибка.
Вывод в том, что при написании макроса с объявлением локальной переменной во вложенном блоке, например в do {} while (0), нужно следить, чтобы имя переменной было уникально и макрос не раскрылся в
struct A *a = a;
именно поэтому:
1. макросы зло
2. имена переменных в них нужно выбирать такими, чтобы вероятность получить подобную ошибку была практически нулевой. Например, используя 2 подчеркивания в середине имени переменной.
> нужно следить, чтобы имя переменной было уникальноНу так и поручите это компилятору. Хорошо, я Вам покажу как это сделать:
#define DUMP(x) \
do { \
struct A *tmp_##x = x; \
printf("%d,%d\n", tmp_##x->k1, tmp_##x->k2); \
} while (0)Теперь у Вас имя временной переменной никогда не совпадёт с аргументом макроса, потому что имя временной переменной строится из имени аргумента макроса с добавлением префикса tmp_
Но у Вас проблема не только в этом, сам макрос выглядит глупо. Во-первых, зачем вообще временная переменная? Во-вторых, какой смысл такого макроса, Вы же не будете для каждого типа структур писать свой DUMP()?
Независимо от степени одаренности программиста компилятор за такие фокусы должен больно бить по рукам, голове и жопе, а не сегфолтиться.В моей практике сегфолтился один из достаточно экзотических компиляторов, если в методе описать дектруктор но забыть про конструктор (конструктор там быть обязан всегда).
> struct A *tmp_##x = x; \оператора ## нет в стандарте с89
> зачем вообще временная переменная?
чтобы поведение кода не изменилось после замены макроса на функцию.
Например DUMP(k++) увеличил k только один раз.> Вы же не будете для каждого типа структур писать свой DUMP()?
Конечно буду. Поскольку у разных структур свой набор полей.
> оператора ## нет в стандарте с89хотя нет, есть.
Но помню с ним были какие-то проблемы, в частности компилятор от MS с ним работает немного по-другому нежели gcc.
>> оператора ## нет в стандарте с89
>хотя нет, есть.А даже если и так. Ещё лет 10 под C89 писать будете? Имея ввиду экзотические возможные условия героического псевдопортирования? А ведь на дворе 2011-ый год уже...
Имхо, вы занимаетесь ерундой. Почему макрос, а не функция? Хотите сэкономить полтора машинных такта в 2010 году? Пишите отладочную функцию, во время отладки замедление нестрашно (если оно вообще будет заметно), а после удалите определение функции и сделайте пустой макрос. #ifdef в помощь
> Почему макрос, а не функция?Макрос имеет преимущества: __LINE__ и __FILE__.
Для отладки бывает полезно знать, по каким веткам работает код, особенно если это state-машина, да еще на кернеле.
Писать вызов функции
DUMP(k, __LINE__, __FILE__)
длиннее чем вызов макроса
DUMP(k)> замедление нестрашно
никакого замедления: static inline функция практически эквивалентна макросу.
Можно еще добавить __attribute__((always_inline)) для полной уверенности :)
А почему не функция с переменным числом параметров ? Ну как-то такvoid mylog(const char *f, ...) {
static struct tm *curr;
static time_t curr_t;
static char w[100];
va_list args;curr_t = time(NULL);
curr = localtime(&curr_t);
strftime(w, 100, "%d-%m-%y %T", curr);
fprintf(stdout, "%s ", w);va_start (args, f);
vfprintf (stdout, f, args);
va_end (args);
fprintf(stdout, "\n");
fflush(stdout);}
Потом сам вызов можно делать из макроса с автоматической подстановкой номера строки и имени файл. Для подключения функции нужен соответствующий хидер,а в нем разбор значения какой-нибудь DEBUG. В общем тут уже писали - на дворе 21 век и надо все-таки как-то соответствовать.
GCC 3.4.6, 4.1.2, 4.2.4 этот код с -Wall -pedantic -O2 собирают и он выполняется без сегфолта, проблема началась с серии 4.3 и присутствует в 4.4 4.5 и 4.6clang 2.8 собирает без предупреждений но выдает Illegal instruction
icc10 - 12:
icc12: command line remark #10148: option '-pedantic' not supported
x.c(9): warning #592: variable "a" is used before its value is set
struct A *a = a;
^icc: command line remark #10148: option '-pedantic' not supported
x.c(6): remark #1418: external function definition with no prior declaration
int foo(struct A *a)
^x.c(9): remark #1599: declaration hides parameter "a" (declared at line 6)
struct A *a = a;
^x.c(9): warning #592: variable "a" is used before its value is set
struct A *a = a;
^x.c(6): remark #869: parameter "a" was never referenced
int foo(struct A *a)
^
так что камни не в огород GCC, icc и clang это тоже выполнять не хотят :)
>>так что камни не в огород GCC, icc и clang это тоже выполнять не хотят :)Пускай не выполняют - в коде бага.
Проблема в том, что gcc компилирует бажный код в непонятно что без предупреждений.ЗЫ Sun сс компилирует правильно.
> Проблема в том, что gcc компилирует бажный код в непонятно что без предупреждений.Так включите предупреждения про инициализацию переменной самой собой: -Winit-self
И что значит в непонятно что и как можно правильно скомпилировать int *a = a? Это undefined behavior, скажите спасибо что компилятор вам диск не отформатировал увидев такую чушь.
>> -Winit-selfспасибо за опцию.
>> Это undefined behavior
нет, это ошибка в программе.
Кстати, gcc ее обнаруживает, но только не во вложенном блоке.$cat y.c
int bar(int k)
{
int k = k;
return k;
}$gcc y.c
y.c : In function 'bar':
y.c :3: error: 'k' redeclared as different kind of symbol
y.c :1: note: previous definition of 'k' was here$cat z.c
int bar(int k)
{{
int k = k;
return k;
}}$gcc z.c
без ошибок.
Наконец-то баг с графитом и cairo исправили, молодцы.