LINUX.ORG.RU

Баги, баги, баги в obconf, но почему так?

 , , ,


0

2

Наверное, у меня голова устала - но в obconf есть баг.

Я его пофиксил (пока полностью не тестировал, т.к. не разобрался пока, как установить его не в систему, а куда-то в отдельную директорию, т.к. он ищет obconf.ui в /usr/local/share/obconf/obconf.ui, кто подскажет - скажу спасибо), а ставить туда что-то в обход пакетного менеджера мне не хочется. В оригинальном коде obconf есть такая строчка:

obc_tab = MAX((atoi(argv[++i]) - 1), 0);
На ней и происходит падение. Я методом проб и ошибок нашел, что gint (а это тип переменной obc_tab) и atoi плохо дружат, хотя везде в гугле ещё 3 года назад все рекомендовали делать именно так, мол проблем быть не должно. Код, исправленный на такую корявую конструкцию
int tmp_obc_tab=atoi(argv[++i]);
if(tmp_obc_tab > 0)
{
    obc_tab = tmp_obc_tab-1;
}
else
{
    obc_tab = 0;
}
не падает. Внимание - вопрос: «Что сделали такого, что код, который раньше работал стал падать, и как можно исправить проблему, не делая некрасивых костылей с временными переменными?»

★★★★★

Ответ на: комментарий от powerguy

Это всё ясно. Ты лучше скажи, как сделать это без временной переменной? Переписывать 100500 строк кода как-то неправильно, тогда уж проще с 0 писать.

peregrine ★★★★★
() автор топика

obc_tab = MAX((atoi(argv[++i]) - 1), 0);

макрос MAX разворачивается так:

#define MAX(a, b)  (((a) > (b)) ? (a) : (b))
и из-за этого ++i может выполняться два раза, а не один.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Спасибо. Ну от макроса я избавился сразу, он мне не понравился, т.к. падал он через раз. Меня больше интересует, почему такая конструкция тоже падает:

obc_tab=atoi(argv[++i]);

peregrine ★★★★★
() автор топика
Последнее исправление: peregrine (всего исправлений: 2)

А макрос чинится так:

#include <glib.h>
#include <stdio.h>

#ifdef FIX_MAX_MACRO
#undef MAX
#define MAX(a,b) ({ typeof(a) _a = (a); typeof(b) _b = (b); _a > _b ? _a : _b; })
#endif

int main(void)
{
  int b = 0;
  int a = MAX(++b, 0);

  printf("a = %d (expected %d)\n", a, 1);
  printf("b = %d (expected %d)\n", b, 1);
  return 0;
}
$ gcc `pkg-config --cflags --libs glib-2.0` q.c && ./a.out 
a = 2 (1 expected)
b = 2 (1 expected)

$ gcc -DFIX_MAX_MACRO `pkg-config --cflags --libs glib-2.0` q.c && ./a.out 
a = 1 (1 expected)
b = 1 (1 expected)

Расширения эти GCC-специфичны, но Clang их тоже понимает.

i-rinat ★★★★★
()
Ответ на: комментарий от peregrine

Меня больше интересует, почему такая конструкция тоже падает:

Запусти в gdb и посмотри, что именно в atoi передаётся. А то, может, там выход за границы argv.

i-rinat ★★★★★
()
Последнее исправление: i-rinat (всего исправлений: 1)

т.к. он ищет obconf.ui в /usr/local/share/obconf/obconf.ui, кто подскажет - скажу спасибо)

./configure --prefix=/tmp/

ставить туда что-то в обход пакетного менеджера мне не хочется.

ПМ ставит в /usr/, а НЕ в /usr/local/ Т.ч. смело ставь.

Я методом проб и ошибок нашел, что gint (а это тип переменной obc_tab) и atoi плохо дружат

что-то ты делаешь не так. int должен нормально кастоваться В gint.

MAX(

наверное ошибка здесь. Разверни все макросы командой cpp, и посмотри, во что разворачивается этот твой MAX.

emulek
()
Ответ на: комментарий от i-rinat

и да, специально для тебя придумали fmax, fmaxf, fmaxl - determine maximum of two floating-point numbers

emulek
()
Ответ на: комментарий от emulek

Это в конкретном месте ему нужны int'ы. Кто гарантирует, что в другом месте не понадобится вызывать MAX с параметрами других типов?

специально для тебя придумали

Все твои советы годятся для студентов, которые начинают язык учить. Для того, чтобы делать правки реального кода, они бесполезны. Очнись. Код уже есть, его надо поправить, причём желательно побольше багов сразу, причём с минимальными правками. Твои поучения — пустое сотрясение воздуха.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Очнись. Код уже есть, его надо поправить, причём желательно побольше багов сразу, причём с минимальными правками.

да я-то сознание не терял. Это ты очнись: поставишь один костыль, поставишь другой костыль… Я по опыту знаю, что очень скоро этот твой костыльный говнокод рухнет, и тебя закопает.

Твои поучения — пустое сотрясение воздуха.

да, я знаю. Мало кто из говнокодеров признается, что он — говнокодер. Я уже привык, что на все мои просьбы не срать говнокодом — nobody cares.

emulek
()
Ответ на: комментарий от emulek

Я по опыту знаю, что очень скоро этот твой костыльный говнокод рухнет, и тебя закопает.

А в наличие этого опыта мы должны верить на слово. Да, проходили уже.

Я уже привык, что на все мои просьбы не срать говнокодом — nobody cares.

Вот и слал бы патчи, чтобы починить ошибки или опасные места.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

костыльный говнокод рухнет, и тебя закопает.

А в наличие этого опыта мы должны верить на слово.

да. Потому что мне стыдно признавать свои ошибки, и рассказывать, как я обосрался. Да это и не очень интересно ИМХО.

Вот и слал бы патчи

угу. Мы работаем над этим…

emulek
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.