Бывало ли у вас, что вы безуспешно пытаетесь найти баг, не получается, в конце концов отчаиваетесь и решаетесь на это забить?
У меня за 15 лет разработки моего проекта это было, насколько я помню, два раза. Я думаю – может это баги в Delphi? Тогда уж наверно ничего не поделаешь, разве что написать для пользователей инструкцию – “не делайте так-то, это вызывает проблемы”.
"Ты должен сделать добро из зла, потому что его больше не из чего сделать". АБ Стругацкие.
Здравствуйте, Khimik, Вы писали:
K>Бывало ли у вас, что вы безуспешно пытаетесь найти баг, не получается, в конце концов отчаиваетесь и решаетесь на это забить?
Не было. Один раз искал баг в драйвере 2 месяца, но таки нашел.
В ядре Linux кстати недавно пофиксили баг который воспроизводится раз в несколько месяцев стресс-тестов.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Здравствуйте, Khimik, Вы писали:
K>Бывало ли у вас, что вы безуспешно пытаетесь найти баг, не получается, в конце концов отчаиваетесь и решаетесь на это забить?
Не было. Было, что баг искал несколько месяцев, было, что в итоге находил багу во фреймворке или даже в SQL Server. Но чтобы совсем не нашёл — такого не было.
Здравствуйте, Khimik, Вы писали:
K>Бывало ли у вас, что вы безуспешно пытаетесь найти баг, не получается, в конце концов отчаиваетесь и решаетесь на это забить? K>У меня за 15 лет разработки моего проекта это было, насколько я помню, два раза. Я думаю – может это баги в Delphi? Тогда уж наверно ничего не поделаешь, разве что написать для пользователей инструкцию – “не делайте так-то, это вызывает проблемы”.
Не припомню. Если баг находтся в моем проекте/сфере ответственности, то это как незакрытый гештальт для меня — создает дискомфорт. Единственное исключение, если баг находится в проприетарной библиотеке без исходных кодов. Тогда удовлетворюсь тем, что нахожу условия при которых он воспроизводится и придумываю обходной путь. Но если это опенсорс, то полезу в исходники. Мой первый пост на этом форуме, кстати, создан под впечатлением от одного такого расследования — нашел заковыристую ошибку с thread stack guard page hit в дельфиском EurekaLog.
Здравствуйте, Khimik, Вы писали:
K>Бывало ли у вас, что вы безуспешно пытаетесь найти баг, не получается, в конце концов отчаиваетесь и решаетесь на это забить? K>У меня за 15 лет разработки моего проекта это было, насколько я помню, два раза. Я думаю – может это баги в Delphi? Тогда уж наверно ничего не поделаешь, разве что написать для пользователей инструкцию – “не делайте так-то, это вызывает проблемы”.
Такое бывает с гейзенбагами, когда ошибка воспроизводится не всегда при одних и тех же шагах, что например вызвано условиями гонки или дедлоками потоков или БД-транзакций. Чтобы такой баг починить, нужно этими компетенциями обладать, чтобы увидеть в коде такую проблему даже без воспроизведения бага.
Здравствуйте, ArtDenis, Вы писали:
AD>А какие средства были использованы для поиска бага?
Обычные средства Delphi: установка чекпоинта в нужном месте кода, пошаговая отладка, средства для просмотра значений переменных во время отладки и т.д. Я на знаю, какие средства отладки используются в других языках.
"Ты должен сделать добро из зла, потому что его больше не из чего сделать". АБ Стругацкие.
Здравствуйте, Khimik, Вы писали:
K>Бывало ли у вас, что вы безуспешно пытаетесь найти баг, не получается, в конце концов отчаиваетесь и решаетесь на это забить?
Нет. В конце концов, все налаживалось. Иногда это занимало очень много времени.
K>У меня за 15 лет разработки моего проекта это было, насколько я помню, два раза. Я думаю – может это баги в Delphi? Тогда уж наверно ничего не поделаешь, разве что написать для пользователей инструкцию – “не делайте так-то, это вызывает проблемы”.
Я ловил пару раз багу в компиляторе. Ну ничего, переписываешь код как-то по-другому, и оно работает.
Здравствуйте, Khimik, Вы писали:
K>Обычные средства Delphi: установка чекпоинта в нужном месте кода, пошаговая отладка, средства для просмотра значений переменных во время отладки и т.д. Я на знаю, какие средства отладки используются в других языках.
Т.е. баг воспроизводился в отладке и его не удалось исправить? Для меня это анрил. Я-то подумал, что речь о багах, которые воспроизводиться у пользователя раз в год и причину которых проще отнести к переключению ячейки памяти компа из-за попадания нейтрино из окрестностей чёрной дыры
Здравствуйте, ArtDenis, Вы писали:
AD>Здравствуйте, Khimik, Вы писали:
K>>Обычные средства Delphi: установка чекпоинта в нужном месте кода, пошаговая отладка, средства для просмотра значений переменных во время отладки и т.д. Я на знаю, какие средства отладки используются в других языках.
AD>
AD>Т.е. баг воспроизводился в отладке и его не удалось исправить? Для меня это анрил. Я-то подумал, что речь о багах, которые воспроизводиться у пользователя раз в год и причину которых проще отнести к переключению ячейки памяти компа из-за попадания нейтрино из окрестностей чёрной дыры
У меня в данном случае, из-за которого я написал этот пост, ошибка срабатывает на сторонних компонентах Delphi — VCL. Если это не баг Delphi, по идее наиболее вероятно что программа где-то пишет данные в динамический массив и выходит за его пределы. В Delphi нет проверок выхода за границы динамического массива, понятно что их и не должно быть из-за скорости. В последнее время я использую собственные динамические массивы на основе "статических классов" с дженериками, в которых есть проверка выхода за границы, но не сформировалась привычка всегда их использовать, опять же из-за скорости.
"Ты должен сделать добро из зла, потому что его больше не из чего сделать". АБ Стругацкие.
Здравствуйте, Khimik, Вы писали:
K>Бывало ли у вас, что вы безуспешно пытаетесь найти баг, не получается, в конце концов отчаиваетесь и решаетесь на это забить? K>У меня за 15 лет разработки моего проекта это было, насколько я помню, два раза. Я думаю – может это баги в Delphi? Тогда уж наверно ничего не поделаешь, разве что написать для пользователей инструкцию – “не делайте так-то, это вызывает проблемы”.
История длиною в лет пять как минимум думаю, а может и даже больше
Был у нас баг, который приводил к синему экрану.
Переписывали весь код, проверили с 146% покрытием, но иногда у клиентов проскакивал.
Было "решение" в виде отключения функциональности и наша поддержка быстро это делала, а снимок памяти к нам так и не доходил.
В общем забили на проблему пока наконец не пришёл снимок памяти, и выяснилось что мы запускали 32-битный код в 64-битном процессе
А всё потому, что имелось 2 (ДВЕ) почти одинаковые функции определения архитектуры процесса.
Но они всё таки немного отличались и в итоге неправильно иногда определяли архитектуру.
Вывод, иногда стоит просто оставить и пойти за пивом
Здравствуйте, Khimik, Вы писали:
K>В Delphi нет проверок выхода за границы динамического массива, понятно что их и не должно быть из-за скорости.
Да ты знаток:
program Project1;
{$APPTYPE CONSOLE}
{$RANGECHECKS ON}uses
System.SysUtils;
var
a:array of byte;
begin
try
SetLength(a, 100);
a[100] := 1;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
ReadLn;
end.
Здравствуйте, rudzuk, Вы писали:
R>Здравствуйте, Khimik, Вы писали:
K>>В Delphi нет проверок выхода за границы динамического массива, понятно что их и не должно быть из-за скорости.
R>Да ты знаток: R>
Здравствуйте, Khimik, Вы писали:
K> Спасибо, не знал.
Поражает, как можно 15 лет пилить код и не знать о таких вещах...
K> {$RangeChecks On} можно указать в головном модуль проекта, или придётся эту строку добавлять в каждый модуль?
Для всего проекта это включается в настройках проекта (Delphi Compiler\Compiling\Runtime errors), директива в файле действует только на файл.
Здравствуйте, Khimik, Вы писали:
K>Бывало ли у вас, что вы безуспешно пытаетесь найти баг, не получается, в конце концов отчаиваетесь и решаетесь на это забить?
1) За последние примерно двадцать лет программирования, такое было у меня может пару-тройку раз.
2) Забить — никогда на такое не решился бы. Даже зная, что источник проблем — не мой код, а что-либо другое.
То есть — в любом случае предпринимаю шаги по решению проблемы. Однако, прежде всего, я пытаюсь проанализировать причину.
После мозгового штурма (детального анализа), часто раскрывается или суть проблемы, или пути её детальной диагностики.
K>Я думаю – может это баги в Delphi?
Пользуешься до сих пор Delphi
Тогда у меня даже нет слов...
Но и сочуствия также нет...
K>Тогда уж наверно ничего не поделаешь, разве что написать для пользователей инструкцию – “не делайте так-то, это вызывает проблемы”.
Совсем тупиковый путь.
Путь к потере Заказчика/Места_работы, возможности продвижения своего продукта.
ИМХО наиболее верно — найти причину проблемы и решить её "на_своём_уровне".
P.S. Раскрою понятие "на_своём_уровне" — поясню на двух примерах:
1) Разработаанное на C++, MFC наше Desktop application (работающее в диспетчерской службе в режиме 24/7)
падает (краш) в произвольные моменты времени. Обычно после 2...3 и более часов работы.
2) Я портровал приложение (C++, MFC) с MSVC2003 на MSVC2008.
После этого, при приёме по сети (UDP) данных от внешнего аппаратного контроллера, иногда наблюдалось UB (включая зависания или краш).
Анализ случая 1 показал, что имеет место утечка памяти. В наших кодах применялись smart-pointers, и проблем не было.
В то же время, замена третье-стороннего ActiveX компонента, на аналогичный (более новой версии) помогла решить проблему.
Анализ случая 2 выявил, что в некоторых пакетах от контроллера идут метки времени в виде переменных типа time_t.
Вот такие: https://en.wikipedia.org/wiki/Unix_time эти переменные сериализуются в последовательный битовый поток,
который передаётся в различные компоненты приложения.
Для MSVC2003 тип данных time_t содержит 4-ре байта, а для MSVC2008 — соответственно 8-мь байт.
Внесение корректировок в код приложения, позволило решить данную проблему.
Т.е. первый случай — это просто уровень замены готового внешнего компонента (черного ящика).
Второй случай — уровень доработок нашего (ранее разработанного) кода.
P.S. Описал случаи семи-восьми-летней давности. Сейчас, разрабатывая на Qt5, я не использую ни древних ActiveX компонентов,
ни старых типов данных. Посему, разработка и отладка приложений проходит намного проще.
Здравствуйте, AlexGin, Вы писали:
AG> Пользуешься до сих пор Delphi
Как тысячи компаний во всем мире.
AG> Но и сочуствия также нет...
Для себя прибереги.
Здравствуйте, Khimik, Вы писали:
K>Бывало ли у вас, что вы безуспешно пытаетесь найти баг, не получается, в конце концов отчаиваетесь и решаетесь на это забить? K>У меня за 15 лет разработки моего проекта это было, насколько я помню, два раза. Я думаю – может это баги в Delphi? Тогда уж наверно ничего не поделаешь, разве что написать для пользователей инструкцию – “не делайте так-то, это вызывает проблемы”.
Нет. Багов, которые невозможно поймать в отладчике, было много (типа, возникает у пользователя Х раз в неделю)
Но даже такие все равно ловятся логами, в том или ином виде. Просто логгирование должно быть достаточным.
Здравствуйте, rudzuk, Вы писали:
R>Поражает, как можно 15 лет пилить код и не знать о таких вещах...
Так это же классно. Перед ТС ещё столько открытий в той области, где он давно уже обитает ))
Я бы порекомендовал ему погуглить и почитать о других средствах (доступных даже для дельфи), таких как например отладочные менеджеры памяти и генераторы крэш-репортов. Возможно он ещё кучу багов с помощью их найдёт
Здравствуйте, rudzuk, Вы писали:
K>> {$RangeChecks On} можно указать в головном модуль проекта, или придётся эту строку добавлять в каждый модуль?
R>Для всего проекта это включается в настройках проекта (Delphi Compiler\Compiling\Runtime errors), директива в файле действует только на файл.
У меня вроде такой ошибки с динамическим массивом нет, а баг остался. Может быть у меня где-то код обращается к свойству класса, который не инициализирован или который финализирован? Я не помню, по умолчанию такие ошибки срабатывают? Можно ли включить их проверку?
"Ты должен сделать добро из зла, потому что его больше не из чего сделать". АБ Стругацкие.
Здравствуйте, ArtDenis, Вы писали:
AD>Я бы порекомендовал ему погуглить и почитать о других средствах (доступных даже для дельфи), таких как например отладочные менеджеры памяти и генераторы крэш-репортов. Возможно он ещё кучу багов с помощью их найдёт
Сходу не нагуглил, можно в двух словах, что это такое? Менеджер памяти — это что-то вроде моего сборщика мусора