|
|
3.3, k0l0b0k (??), 18:48, 17/12/2010 [^] [^^] [^^^] [ответить]
| +/– |
4.5.1 сегфолтится на моем "изобретении". багрепорт решил не писать до обновления. Вот до арча 4.5.2 доползет - попробую...
| |
|
4.14, Аноним (-), 00:45, 18/12/2010 [^] [^^] [^^^] [ответить]
| +1 +/– |
> 4.5.1 сегфолтится на моем "изобретении". багрепорт решил не писать до обновления. Вот до арча 4.5.2 доползет - попробую...
Ага, жди у моря погоды.
| |
|
|
|
1.7, anon2 (?), 21:12, 17/12/2010 [ответить] [﹢﹢﹢] [ · · · ]
| –3 +/– |
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.
| |
|
2.10, Аноним (-), 22:16, 17/12/2010 [^] [^^] [^^^] [ответить]
| +7 +/– |
> struct A *a = a;
Поздравляю, вы выиграли медаль «Гений программирования».
| |
|
3.12, anon2 (?), 23:36, 17/12/2010 [^] [^^] [^^^] [ответить]
| +/– |
>> struct A *a = a;
> Поздравляю, вы выиграли медаль «Гений программирования».
Чуть-чуть сильнее напрягите извилины.
Это сейчас очевидно где ошибка.
Вывод в том, что при написании макроса с объявлением локальной переменной во вложенном блоке, например в do {} while (0), нужно следить, чтобы имя переменной было уникально и макрос не раскрылся в
struct A *a = a;
| |
|
4.13, BSA (?), 23:50, 17/12/2010 [^] [^^] [^^^] [ответить]
| +1 +/– |
именно поэтому:
1. макросы зло
2. имена переменных в них нужно выбирать такими, чтобы вероятность получить подобную ошибку была практически нулевой. Например, используя 2 подчеркивания в середине имени переменной.
| |
4.16, Аноним (-), 02:05, 18/12/2010 [^] [^^] [^^^] [ответить]
| +/– |
> нужно следить, чтобы имя переменной было уникально
Ну так и поручите это компилятору. Хорошо, я Вам покажу как это сделать:
#define DUMP(x) \
do { \
struct A *tmp_##x = x; \
printf("%d,%d\n", tmp_##x->k1, tmp_##x->k2); \
} while (0)
Теперь у Вас имя временной переменной никогда не совпадёт с аргументом макроса, потому что имя временной переменной строится из имени аргумента макроса с добавлением префикса tmp_
Но у Вас проблема не только в этом, сам макрос выглядит глупо. Во-первых, зачем вообще временная переменная? Во-вторых, какой смысл такого макроса, Вы же не будете для каждого типа структур писать свой DUMP()?
| |
|
5.21, ram_scan (?), 17:13, 18/12/2010 [^] [^^] [^^^] [ответить]
| +1 +/– |
Независимо от степени одаренности программиста компилятор за такие фокусы должен больно бить по рукам, голове и жопе, а не сегфолтиться.
В моей практике сегфолтился один из достаточно экзотических компиляторов, если в методе описать дектруктор но забыть про конструктор (конструктор там быть обязан всегда).
| |
5.23, anon2 (?), 18:51, 18/12/2010 [^] [^^] [^^^] [ответить]
| +/– |
> struct A *tmp_##x = x; \
оператора ## нет в стандарте с89
> зачем вообще временная переменная?
чтобы поведение кода не изменилось после замены макроса на функцию.
Например DUMP(k++) увеличил k только один раз.
> Вы же не будете для каждого типа структур писать свой DUMP()?
Конечно буду. Поскольку у разных структур свой набор полей.
| |
|
6.24, anon2 (?), 19:05, 18/12/2010 [^] [^^] [^^^] [ответить]
| +/– |
> оператора ## нет в стандарте с89
хотя нет, есть.
Но помню с ним были какие-то проблемы, в частности компилятор от MS с ним работает немного по-другому нежели gcc.
| |
|
7.25, Анонимбус (?), 23:30, 18/12/2010 [^] [^^] [^^^] [ответить]
| +/– |
>> оператора ## нет в стандарте с89
>хотя нет, есть.
А даже если и так. Ещё лет 10 под C89 писать будете? Имея ввиду экзотические возможные условия героического псевдопортирования? А ведь на дворе 2011-ый год уже...
| |
|
6.26, Аноним (-), 17:37, 19/12/2010 [^] [^^] [^^^] [ответить]
| +/– |
Имхо, вы занимаетесь ерундой. Почему макрос, а не функция? Хотите сэкономить полтора машинных такта в 2010 году? Пишите отладочную функцию, во время отладки замедление нестрашно (если оно вообще будет заметно), а после удалите определение функции и сделайте пустой макрос. #ifdef в помощь
| |
|
7.27, anon2 (?), 17:03, 20/12/2010 [^] [^^] [^^^] [ответить]
| +/– |
> Почему макрос, а не функция?
Макрос имеет преимущества: __LINE__ и __FILE__.
Для отладки бывает полезно знать, по каким веткам работает код, особенно если это state-машина, да еще на кернеле.
Писать вызов функции
DUMP(k, __LINE__, __FILE__)
длиннее чем вызов макроса
DUMP(k)
> замедление нестрашно
никакого замедления: static inline функция практически эквивалентна макросу.
Можно еще добавить __attribute__((always_inline)) для полной уверенности :)
| |
|
|
|
|
|
2.28, Прохожий старый анонимус (?), 11:04, 21/12/2010 [^] [^^] [^^^] [ответить]
| +/– |
А почему не функция с переменным числом параметров ? Ну как-то так
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 век и надо все-таки как-то соответствовать.
| |
|
1.8, Sylvia (ok), 21:23, 17/12/2010 [ответить] [﹢﹢﹢] [ · · · ]
| +1 +/– |
GCC 3.4.6, 4.1.2, 4.2.4 этот код с -Wall -pedantic -O2 собирают и он выполняется без сегфолта, проблема началась с серии 4.3 и присутствует в 4.4 4.5 и 4.6
clang 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)
^
| |
|
2.9, Sylvia (ok), 21:26, 17/12/2010 [^] [^^] [^^^] [ответить]
| +/– |
так что камни не в огород GCC, icc и clang это тоже выполнять не хотят :)
| |
|
3.11, anon2 (?), 23:23, 17/12/2010 [^] [^^] [^^^] [ответить]
| +/– |
>>так что камни не в огород GCC, icc и clang это тоже выполнять не хотят :)
Пускай не выполняют - в коде бага.
Проблема в том, что gcc компилирует бажный код в непонятно что без предупреждений.
ЗЫ Sun сс компилирует правильно.
| |
|
4.17, Аноним (-), 02:21, 18/12/2010 [^] [^^] [^^^] [ответить]
| +5 +/– |
> Проблема в том, что gcc компилирует бажный код в непонятно что без предупреждений.
Так включите предупреждения про инициализацию переменной самой собой: -Winit-self
И что значит в непонятно что и как можно правильно скомпилировать int *a = a? Это undefined behavior, скажите спасибо что компилятор вам диск не отформатировал увидев такую чушь.
| |
|
5.22, anon2 (?), 18:36, 18/12/2010 [^] [^^] [^^^] [ответить]
| +/– |
>> -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
без ошибок.
| |
|
|
|
|
|