Pull to refresh

Comments 13

Разработчики LLVM как-то отреагировали на столь обширный баг-репорт?

У вас не возникает ощущения, после столько лет и стольких багов, что спасти разработку на C++ может только переход на другой язык, либо изменение самогО С++, чтобы он сам стал другим, более safe, языком? Вопрос конечно больше риторический.

Посмеялся над комментарием:

Could LLVM board request PVS license (for open source even free?) to periodically check for errors so community can help with fixes (ideally before release to avoid **public "shame"** like now that just recently released LLVM has some trivial bugs)

И смешно, и грустно. На самом деле, я понимаю эту боль, т.к. сам руковожу проектами. Беда в том, что даже когда отдельно взятые разработчики понимают важность выявления ошибок на раннем этапе, не всегда у них есть мотивация это делать. Т.к. например им платят за фичи (их количество) и скорость их реализации, а не за качество (например, за качество отвечают другие выделенные люди). В open-source проекте всё еще сложнее, т.к. откуда там деньги, кто оплачивает бал, какие приоритеты он ставит, как делят разработчики задачи между собой — очень много вопросов, которые требуют ОЧЕНЬ качественного и профессионального технического менеджмента. А есть ли он, такой менеджмент? Не факт.

Да, лучше они раз показать, чем 100 раз рассказать. Очень крутой анализатор, жаль для Delphi нет такого.

Для Delphi мы делали самописное "поделие" на тему тех багов, которые допускали мы сами. Но оно уровня студенческой лабы, на бОльшее ресурсов не хватило — надо было пилить основные проекты.
Можно скачать по этой ссылке

Чтобы снизить количество таких ошибок, рекомендую всегда оформлять однотипные операции табличным методом.

В хорошо оформленном коде, конечно, легче находить ошибки, но оформление не поможет их полностью исключить.

Я бы обобщил так, что не только операторы сравнения, но и вообще любые попольные операции являются ОЧЕНЬ опасным местом. По крайней мере, в моей практике пара ошибок уезжала к пользователям. Например:

for each (auto entry in entries)
{
        sciter::value item;
        item.set_item("DisplayName",  entry.DisplayName);
        item.set_item("IsFolder",     entry.IsFolder);
        item.set_item("IconPath",     entry.IconPath);
        item.set_item("FilePath",     entry.FilePath);
        item.set_item("LocalName",    entry.RelativeFolderName); // Oops, I did it again!
        items.append(item);
}


Пример из реального проекта. Потом плюсовый код в другом месте соединялся с кодом скриптов и… бум. В итоге, я решил в принципе избавиться от копипасты имён полей, чтобы такую ошибку было буквально негде совершить:

for each (auto entry in entries)
{
#define STR_VALUE(arg) #arg
#define SET_ITEM(field) item.set_item(STR_VALUE(field), entry.field)
        sciter::value item;
        SET_ITEM(DisplayName);
        SET_ITEM(IsFolder);
        SET_ITEM(IconPath);
        SET_ITEM(FilePath);
        SET_ITEM(LocalName);
#undef SET_ITEM
#undef STR_VALUE
        items.append(item);
}


Да, кто-то скажет, что лечение хуже болезни. Но оно, по крайней мере, лечит (в отличие от оформления). Если написать для кода №3 что-то типа COMPARE_TO_THIS(other, field)… по крайней мере, случайно *this не напишешь. И, в отличие от моего примера, им можно пользоваться часто, то есть, объявить один раз на весь проект.

Если кто-то знает более изящный способ решения этой проблемы — но именно решения! — поделитесь, пожалуйста.

Я бы сделал примерно так:

for each (auto entry in entries) {         

sciter::value item;  

std::unordered_map<char * ,decltype(entry.DisplayName)> data={
    {"DisplayName",  entry.DisplayName},
    {"IsFolder",     entry.IsFolder},{"IconPath",     entry.IconPath},
    {"IconPath",     entry.IconPath},
    {"FilePath",     entry.FilePath},
    {"LocalName",    entry.RelativeFolderName}
}

for(auto &[S,F]:data){
    item.set_item(S,F);
}
items.append(item);
}

Так по мне выглядит красивее, и копипаст почти убирается.

Если формировать data в другом месте, то можно избавится и от многих других опечаток.

Кажется, автор намекал не на сам факт копипасты, а на её последствия: ключу "LocalName", по всей видимости, должно было соответствовать значение entry.LocalName, а не RelativeFolderName.

подозрительная строчка:

return std::make_pair(Addr, Delta64);

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

return std::make_pair(Addr, PointerEdgeKind);

Ошибка c new ничем не удивляет, когда заглядываешь в нормальный справочник и оказывается, что абсолютное большинство "справочников" в сети и "комментариев в гайдах по программированию" нагло умалчивают об том, что он соответствует malloc. И следовательно не нужно забывать про delete или free(). Более скажу, ни одна гадюка даже на Хабр об этом ни разу не сказала.

Sign up to leave a comment.