Войти
ФлеймФорумПрограммирование

Летопись багов

Страницы: 1 2 311 12 Следующая »
#0
11:30, 3 ноя. 2015

A terribly depressing bug hunt can feel sort of worth it if there is a teachable lesson or structural solution at the end of it.

John Carmack ( https://twitter.com/id_aa_carmack/status/284830336737742848 )

В этой теме каждый желающий может централизованно выкладывать свои побеждённые баги.
Для того, чтобы выплеснуть эмоции, "чтобы не забылось", чтобы дать другим источник для вдохновения в поисках, чтобы набрать статистику, потому что баг весёлый был, да мало ли зачем.

Я не знаю, взлетит ли идея, ну вот и посмотрим.


#1
(Правка: 11:33) 11:32, 3 ноя. 2015

f(x) не равно f(x)

+ Показать
+ Показать
+ Показать
+ Показать
#2
11:35, 3 ноя. 2015

Я почти начинаю, но Тарас меня опередил.

Два тупых, невдохновляющих, житейских бага. Однако пару часов они мне стоили.

1-й баг.
Есть строчка текста длиной в len символов, собираюсь её нарисовать на экране. Собираю VB (в системной памяти) из 2 треугольников на букву, и говорю:

render_vb(
  vb.data(),
  len*6,
  GL_TRIANGLES,
  2,4,0,3);
(внутре там glDrawArrays). Рисуется то, что надо, плюс фигня.
Решение: Пробел не генерирует квада (2-х треугольников), в буфере мало данных.
Исправление:
render_vb(
  vb.data(),
  vb.size()/9,
  GL_TRIANGLES,
  2,4,0,3);

2-й баг.
Звуковой движок (типа OpenAL, только тупее). Удаление буфера. Вызывает:

static void clean_buffer(si32 id)
{
    if(valid_buf_id(id))
    {
        buffer &buf=buffers[id];
        buf.free=true;
        buf.fmt=0;
        buf.size=0;
        if(buf.data)
            delete[] buf.data;
    }
}
Падение.
Решение: функция вызывается несколько раз, соответственно - multiple-free.
Исправление:
static void clean_buffer(si32 id)
{
    if(valid_buf_id(id))
    {
        buffer &buf=buffers[id];
        buf.free=true;
        buf.fmt=0;
        buf.size=0;
        if(buf.data)
            delete[] buf.data;
        buf.data=nullptr;
    }
}

Интересно то, что я некоторое время думал, что баги связаны между собой (случайные изменения в 1-м влияли на падения).

#3
12:10, 3 ноя. 2015

FordPerfect
> delete[]

#4
12:25, 3 ноя. 2015

Сколько-то лет назад был забавный баг, когда удаление одного элемента из std::set удаляло чуть ли не половину контейнера. Оказалось, у этого элемента часть ключа - float получался nan (в силу другого бага). А в реализации сета даже для одного элемента делается equal_range, и удаляется весь рейнж.

#5
(Правка: 13:28) 13:21, 3 ноя. 2015

TarasB
Отличные картинки с водоплавающими питухами

#6
(Правка: 13:29) 13:27, 3 ноя. 2015

TarasB
> делит
Нашёл ещё один баг?))) Очень распространённый?

krian
А вот интересно, поидеи в трии сет можно класть флоат, но с осторожностью. Поэтому никогда так не рисковал. Насчёт нана - я считаю можно было исправить, подправив компаратор

#7
(Правка: 15:04) 14:58, 3 ноя. 2015

А, ещё вспомнил, чужой баг. Человек делал как-то так:

int field_ = -1;
f << (int8)field_;

field_ = 0;
f >> (int8&)field_;

Правка: неправильно баг рассказал.

laMer007
Да так-то можно, почему нет, до тех пор, пока сравнения остаются транзитивными и антисимметричными.

#8
15:01, 3 ноя. 2015

krian
f - файловый поток? Я голову долго ломал, почему сдвигаем, но не сохраняем результат.

#9
15:05, 3 ноя. 2015

TarasB
Да, конечно. Только я напутал сначала, там не про то было.

#10
23:41, 3 ноя. 2015

TarasB
>f(x) не равно f(x)
Ты подробнее, подробнее давай...

>delete[]
Ты про то, чтобы все аллокации заворачивать с умные указатели или векторы?
Встроенные векторы там, откуда унаследован код вроде не получались по Объективным Законам ЖизниTM, а остальное... возможно и стоило бы. Инерция мышления, всё такое.

krian
>Сколько-то лет назад был забавный баг, когда удаление одного элемента из std::set удаляло чуть ли не половину контейнера.
Ядрёно! Напомнило https://web.archive.org/web/20151002151248/http://home.comcast.ne… %20bugs%5D%5D (даю такую ссылку, потому что блог, вроде, сейчас лежит).

Ну и раз уж разговор зашёл об этом - вспомню свой.
Считал как-то какую-то математику, которая была по смыслу целочисленная, в плавучке.
Вывожу, соответственно, через printf("%.0f");
Вывожу разность двух величин, которая математически должна быть равна 0.
Выводит 1. Сидел, долго думал.

+ потом решил вывести больше знаков

#11
17:05, 4 ноя. 2015

FordPerfect
> Ты подробнее, подробнее давай...
Да всё то же, 3д-вектор, не удовлетворяющий условию dot(v,n)<c, запихивают в процедуру, где его как-то правят в цикле. Условие выхода из цикла - чтобы вектор удовлетворял условию dot(v,n)<c. После процедуры вектор (который внутри проходил поправку) имеет то же самое значение, что и до входа в неё. Прога повисала от такого.

#12
14:36, 5 ноя. 2015

Ещё вспомнился баг, банальный на самом деле, но хочется интересную тему поддержать.
Итак, гуи, иерархия виджетов на shared_ptr, слабые ссылки вверх на родителя.

+ Показать

И всё было хорошо, пока в какой-то момент не захотелся комплексный контрол, который в себе же строил сразу иерархию с собой в корне. В конструкторе.
Ну дальше, думаю понятно, он в конструкторе добавлял в себя дочерний виджет, этим дёргал свой shared_from_this(), чтобы дать его ребёнку запомнить.
На возврате из Element::_set_parent() этот shared_ptr умирал, зануляя счётчик, вызывая родителю деструктор и освобождая память.

Мораль - two-stage construction рулит.

auto PaletteControl::Create(const Ruleset& rules) -> shared_ptr<PaletteControl>
{
  shared_ptr<PaletteControl> thiz{new PaletteControl{rules}};
  if (!thiz->_init())
    thiz.reset();
  return thiz;
}
#13
15:17, 5 ноя. 2015

Свежий баг

tblib::StringRef lpCmdLine;
tblib::StrBuf hardCmdLine;
...
tblib::StringRef cl = hardCmdLine ? hardCmdLine : lpCmdLine;
...
работаем с cl

стрингреф и стрбуф имеют операторы приведение друг к другу, при приведение рефа к буфу выделяется память, при выделении буфа к рефу просто возвращается указатель

+ Показать

#14
19:57, 7 ноя. 2015
Изображение
Страницы: 1 2 311 12 Следующая »
ФлеймФорумПрограммирование