Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Огромный Калькулятор выходит из под контроля

Anna | 24.06.2014 | нет комментариев
Я хочу посвятить эту статью задаче, о которой немного кто задумывается. Все шире и шире используется моделирование разных процессов с поддержкой компьютера. Это восхитительно, вероятностью экономить время и материалы на бессмысленные химические, биологические, физические и прочие эксперименты. Обдув модели крыла на компьютере может в несколько раз сократить число макетов, которое после этого будет испытываться в реальной аэродинамической трубе. Численным экспериментам доверяют всё огромнее. Впрочем за пиршеством численного моделирования никто не обращает внимания на рост трудности программ. В компьютере и к программам видят каждого лишь инструмент для приобретения итога. Меня беспокоит, что вдалеке не все знают и задумываются о том, что рост размера программы ведет к нелинейному росту числа ошибок. Небезопасно использовать компьютер как легко огромный калькулятор. Я и думаю, нужно доносить эту мысль до других людей.

Огромный калькулятор

В начале, я хотел назвать эту статью примерно так «Если программистам невозможно производить лекарства, то отчего медикам дозволено программировать?». Абстрактному программисту невозможно заняться изобретением и изготовлением лекарств. Повод внятна — у него нет соответствующего образования. А вот с программированием не всё так легко. Кажется, что отвлеченный медик, освоив программирование, механически принесёт пользу. Благо, обучиться как-то программировать проще, чем разобраться в органической химии и тезисах создания лекарств.

Тут кроется подвох. Численный эксперимент требует не меньший аккуратности, чем настоящий. Учат мыть пробирки позже экспериментов и следят за их стерильностью. Но немного кто серьезно обеспокоен задачей, что какой-то массив может нечаянно оказаться неинициализированным.

Программисты знают, что чем труднее программное обеспечение, тем трудней и не явственнее в нём проявляются ошибки. Другими словами, я говорю о нелинейном росте числа ошибок при росте размера кода. А чай программы для химических и иных расчётов отнюдь не примитивны. Тут и кроется напасть. Не ужасно, что медик-программист допускает ошибки. Их делает всякий программист, самостоятельно от профессионализма. Жутко, что таким итогам начинают всё огромнее доверять. Посчитали что-то и пошли дальше заниматься своими делами.

Те, чья основная действие программирование, знают угроза такого подхода. Они знают, что такое неопределенное поведение и как программа может делать вид, что выдает верный итог. Есть статьи и книги, посвященные тому, как верно писать юнит-тесты и как отменнее проверить корректность расчетов.

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

Имею кое-что сказать по этой теме исходя из личного навыка. Будучи профессиональным программистом, по образованию я — наследственный физик. Так уж вышло, что в тот момент, когда я выбирал ВУЗ, голос крови оказался мощнее, чем надежда в ясное грядущее IT. И я поступил в довольно элитную по здешним меркам физическую высшую школу, которая, по сути, является «детским садиком» при огромном НИИ в родном городе Нижнем Новгороде. Люди, знающие тему, узнают и НИИ, и наименование школы.

На протяжении учёбы абсолютно безусловно оказалось, что по части программирования (и в том числе математических способов физического моделирования) я был одним из наилучших. И там же выяснились следующие факты:

1. Физики рассматривают компьютер как огромный универсальный калькулятор, дозволяющий возвести график зависимости Эта от Тэта при Гамма тяготящемся в бесконечность. Причем, явственным образом, для них цель — график, а совсем не та программа, которая его рисует.

2. Как следствие из этого факта, программист — это не профессия. Программист — это легко тот человек, тот, что может пользоваться Огромным Калькулятором, Дабы возвести означенный график. Каким методом график будет построен, не имеет значения. Вовсе. Как-как вы сказали? Статический обзор? Контроль версий? Окститесь, родные! C — язык для программистов.Физики пишут на Фортране!

3. Как следствие из предыдущего пункта, человек, тяготящийся посвятить свою жизнь написанию программ физ. моделирования, даже многофункциональных, даже дюже и дюже резких — не больше, чем приложение к калькулятору. Он и не человек совсем, а так… И это, кстати, распространялось не только на меня (куда уж мне, убогому), а даже и на лучшего численника-расчётчика в НИИ, тот, что преподавал у нас численные способы и тот, что, когда я пришел к нему делать курсовую, сказал мне примерно открытым текстом: «Вас будут презирать, приготовьтесь терпеть».

Терпеть мне не захотелось, и я позже окончания ушел из моделирования в области, где программистов не считают людьми второго сорта. Верю, данный пример поясняет, отчего инициативы типа ввода статического обзора даже на относительно больших (до 20-30 человек) планах по математическому моделированию — гиблое дело. Там легко может не найтись человека, тот, что знает, что это такое. А если такой человек и найдётся, его, скорее каждого затопчут, потому что нафиг не необходимы эти новомодные программистские прибамбасы. Сто лет без них жили — и дальше проживём.

И тем, кто не заскучал, 2-й пример. Мой папа, находясь в пенсионном возрасте, тем не менее работает в дюже огромном оборонно-инженерном предприятии, тут же, в Нижнем (самом огромном в городе и одном из величайших в стране — те, кто в теме вновь же угадают ;) ). Он всю жизнь программировал на Фортране. Начинал еще с перфокарт. Я не виню его за то, что не учит C . Ему это теснее 10 лет назад было поздно — он еще хорошо держится. Но на предприятии, где 2/3 работников что-то как-то программируют, приняты следующие меры безопасности:

1. Никакого интернета. Вовсе. Необходима письменность — иди в местную библиотеку. Stack Overflow? А что это? Даже если ты хочешь отправить письмо электронной почтой, ты должен написать заявление руководителю, где ты объяснишь, кому это письмо и для чего. Интернет «под расписку» есть только у избранных. Известность всевышнему, хоть внутренняя сеть есть.

2. Никаких административных прав на рабочем компьютере. Допустимо, это правило умно для офисного планктона, но мне сложно себе представить программиста, которого бы оно устроило.

3. (не относится к делу, легко иллюстрация) Невозможно даже пронести телефон с камерой (а где вы сейчас видели другие)?

В итоге даже молодняк пишет на Фортране, причем реально грамотных в программировании — единицы. Знаю, потому что подтягивал по программированию одного парня лет 25, тот, что был мне отцом зарекомендован как перспективный.
Мой приговор: там 80-е годы. Даже при том, что там хорошо платят, я не пойду туда ни за какие коврижки.

Вот такие два примера из жизни умственной элиты. Никого не хочу очернить — люди отлично делают своё дело и так, но изредка смотря, с какими ветряными мельницами порой воюет папа, которого я незадолго (известность всевышнему!) сумел-таки пересадить в git, сердце сжимается. Никакого ООП в плане под миллион строк кода, никакого статического обзора.

Легко люди имеют качество быть дюже консервативными в областях, не являющихся их основным «коньком».

(Илья Майзус. Оригинал комментария.)

Самое основное тут, что компьютер это легко Огромный Калькулятор. А раз так, то и знать о нём дозволено не огромнее чем заслуживает его младший родственник — «калькулятор карманный». Да, именно так его и применяют. В различных областях. Давайте на секунду отвлечемся и заглянем в мир физики. Посмотрим, как находит доказательство очередная теория. Для этого мне опять придется привести огромную цитату. Источником является книга Брайана Грина «Изящная вселенная (суперструны, спрятанные размерности и искания окончательной теории)» [1]:

Мы все сгрудились вокруг компьютера Моррисона, стоявшего в нашем кабинете. Аспинуолл объяснил Моррисону, как запустить программу и какой точный вид обязаны иметь вводимые в нее данные. Моррисон привел полученные ночью итоги к надобному виду, и сейчас все было готово.

Расчет, тот, что необходимо было провести, дерзко говоря, сводился к определению массы определенной частицы, являющейся колебательной модой струны при ее движении во вселенной, компоненту КалабиЯу которой мы постигали всю осень. Мы верили, что в соответствии с выбранной нами стратегией масса окажется верно такой же, что и масса в случае разнообразия КалабиЯу, возникшего позже флопперестройки с обрывом пространства. Последнюю массу вычислить было легко, и мы сделали это несколькими неделями прежде. Результат оказался равным 3 в определенной системе единиц, которой мы пользовались. А так как теперь проводился численный расчет на компьютере, то ожидаемый итог должен был быть близким к числу 3, чтото как бы 3,000001 либо 2,999999; различие от точного результата объяснялось бы ошибками округления.

Моррисон сел за компьютер. Его палец завис над клавишей «Enter». Напряжение возрастало. Моррисон выдохнул «поехали» и запустил программу. Через пару секунд компьютер выдал результат: 8,999999. Мое сердце упало. Неужто подлинно флопперестройки с обрывом пространства нарушают зеркальную симметрию, а значит, вряд ли существуют в действительности? Но в следующее же миг мы сообразили, что тут какаято глупая оплошность. Если в массах частиц на 2-х разнообразиях подлинно есть различие, примерно немыслимо, что компьютер выдал бы итог, столь ближний к целому числу. Если наши идеи неверны, то с тем же самым триумфом компьютер мог бы выдать результат, состоящий из абсолютно случайных цифр. Мы получили неверный результат, но неправильность его была такого вида, из которого навязывался итог о том, что гдето мы допустили тривиальную ошибку. Аспинуолл и я подошли к доске, и мгновенно оплошность была обнаружена: мы позабыли множитель 3 в «простом» вычислении несколько недель назад, так что верный итог должен был равняться 9. Следственно результат компьютера — это как раз то, на что мы верили.

Безусловно, совпадение итога позже того, как обнаружена оплошность, является лишь наполовину убедительным. Если знаменит желаемый итог, дюже легко обнаружить метод его получить. Нам неотложно требовался иной пример. Имея все нужные программы, придумать его не представляло трудности. Мы вычислили массу еще одной частицы на верхнем разнообразии КалабиЯу, на данный раз с специальной тщательностью, Дабы избежать еще одной ошибки. Результатом было число 12. Мы вновь окружили компьютер и запустили программу. Через несколько секунд был получен результат 11,999999. Согласие. Мы подтвердили, что полагаемое зеркальное пространство является зеркальным пространством, и флопперестройки с обрывами пространства являются частью теории струн.

Я заскочил со стула и, опьяненный победой, сделал круг по комнате. Моррисон, сияя, сидел за компьютером. И только реакция Аспинуолла была нестандартной. «Здорово. Я и не сомневался, что все так и будет, — спокойно сказал Аспинуолл. — А где мое пиво?»

Я верю, что они гении. Но предположим, что таким подходом вычислялось значение интеграла обычными студентами. Не думаю, что тогда программисты посчитали бы такой подход серьезным. А если бы программа сразу выдала 3? Что тогда? Оплошность в программе посчиталась бы за подтверждение? Думаю, потом бы оплошность всплыла при перепроверке ими же либо другими учеными. Но все равно, «совершенный сферический программист в вакууме» напуган от такого подхода.

Вот такая вот она действительность. Именно так применяются не только персональные компьютеры, но и кластерные системы в научных вычислениях. А самое основное, люди доверяют итогам работы программ. И чем дальше, тем огромнее таких вычислении будет. И тем огромнее будет угроза существования ошибок в их коде.

Быть может пора что-то менять?

Я имею права сам себе наклеить пластырь. Могу порекомендовать, что, по моему суждению, стоит выпить при простуде. Но не больше. Я не могу сверлить зуб либо выписать рецепт.

Быть может, когда ответственность создаваемой программной системы выходит за определённые рамки, её разработчики тоже обязаны подтверждать свою квалификацию?

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

Пример угрозы

Думаю, многим мои переживания кажутся слишком абстрактами. Следственно, давайте разглядим что-то из практики. Есть открытый пакет Trans-Proteomic Pipeline (TPP), для решении задач в сфере биологии. Его очевидно применяют. Применяют его те, кто разрабатывает и допустимо сторонние организации. Мне кажется, присутствие всякий в нем ошибки, теснее потенциальная задача. А есть ли в нём ошибки? Да есть. И возникают всё новые. Год назад, мы проверяли данный план и написали заметку “Проверка плана Trans-Proteomic Pipeline (TPP)“.

Изменилось что-то с тех пор? Ничего не изменилось. План продолжает прогрессировать и обрастать новыми ошибками. Огромный Калькулятор поборол. Разработчики не заняты написанием высококачественного плана с минимально допустимым числом ошибок. Они легко решают задачи. Будь напротив, они бы как-то отреагировали на предыдущую статью и задумались над внедрением каких-то инструментов статического обзора. Я не имею в виду, что они были обязаны предпочесть PVS-Studio. Есть много других статических анализаторов кода. Значимо то, что в ответственном приложении продолжают возникать типичнейшие ошибки. Давайте посмотрим, что есть новенького.

1. Какой-то неумеха продолжает писать неправильные циклы

В предыдущей статье, я теснее писал про некорректные данные в циклах. Есть такие ошибки и новой версии пакета.

double SpectraSTPeakList::calcDot(SpectraSTPeakList* other) {
  ....
  for (i = this->m_bins->begin(), j = other->m_bins->begin(); 
       i != this->m_bins->end(), j != other->m_bins->end();
       i  , j  ) {
    d = (*i) * (*j);
    dot  = d; 
  }
  ....
}

Диагностическое сообщение PVS-Studio: V521 Such expressions using the ‘,’ operator are dangerous. Make sure the expression is correct. spectrastpeaklist.cpp 504

В проверке «i != this->m_bins->end(), j != other->m_bins->end()», выражение стоящее до запятой ничего не проверяет. Оператор запятая ‘,’ применяется для выполнения стоящих по обе стороны от него выражений в порядке слева направо и возвращает значение правого выражения. Правильная проверка должна выглядеть так:

i != this->m_bins->end() && j != other->m_bins->end()

Схожие ляпы дозволено увидеть тут:

  • spectrastpeaklist.cpp 516
  • spectrastpeaklist.cpp 529
  • spectrastpeaklist.cpp 592
  • spectrastpeaklist.cpp 608
  • spectrastpeaklist.cpp 625
  • spectrastpeaklist.cpp 696

2. Разыменовывание нулевого указателя

Такая оплошность не приведет к неправильным итогам вычислений. Будет падание программы, что гораздо отменнее. Впрочем, не написать про эти ошибки будет тоже необычно.

void ASAPRatio_getDataStrctRatio(dataStrct *data, ....)
{
  ....
  int *outliers, *pepIndx=NULL;
  ....
  //pepIndx не изменяется
  ....
  if(data->dataCnts[i] == 1 && pepIndx[i] == 0)  
     data->dataCnts[i] = 0;
  ....
}

Диагностическое сообщение PVS-Studio: V522 Dereferencing of the null pointer ‘pepIndx’ might take place. asapcgidisplay2main.cxx 534

Тут также разыменовывается нулевой указатель:

  • Pointer ‘peptides’. asapcgidisplay2main.cxx 556
  • Pointer ‘peptides’. asapcgidisplay2main.cxx 557
  • Pointer ‘peptides’. asapcgidisplay2main.cxx 558
  • Pointer ‘peptides’. asapcgidisplay2main.cxx 559
  • Pointer ‘peptides’. asapcgidisplay2main.cxx 560
  • Pointer ‘pepIndx’. asapcgidisplay2main.cxx 569

3. Неочищенные массивы

static void clearTagNames() {
   std::vector<const char *>ptrs;
   for (tagname_set::iterator i = tagnames.begin();
        i!=tagnames.end();i  ) {
      ptrs.push_back(*i);
   }
   for (tagname_set::iterator j = attrnames.begin();
        j!=attrnames.end();j  ) {
      ptrs.push_back(*j);
   }
   tagnames.empty();
   attrnames.empty();
   for (size_t n=ptrs.size();n--;) {
      delete [] (char *)(ptrs[n]); // cast away const
   }
}

Анализатор подметил тут сразу два неочищенных массива:

V530 The return value of function ‘empty’ is required to be utilized. tag.cxx 72

V530 The return value of function ‘empty’ is required to be utilized. tag.cxx 73

Взамен функции empty() следует вызывать функцию clear().

4. Неинициализированные объекты классов

class ExperimentCycleRecord {
public:
  ExperimentCycleRecord() {
    ExperimentCycleRecord(0,0,0,True,False);
  }
  ExperimentCycleRecord(long lExperiment, long lCycleStart,
                        long lCycleEnd, Boolean bSingleCycle,
                        Boolean bRangleCycle)
  {
    ....
  }
  ....
}

Диагностическое сообщение PVS-Studio: V603 The object was created but it is not being used. If you wish to call constructor, ‘this->ExperimentCycleRecord::ExperimentCycleRecord(….)’ should be used. mascotconverter.cxx 101

Конструктор ExperimentCycleRecord() не исполняет своего предназначения. Он ничего не инициализирует. Разработч= FFFFFFFBu. А, как вестимо, 4294967291 огромнее 0.

Бунт Большого Калькулятора удаётся. Немного написать верный теоретический алгорифм. Нужно ещё написать верный код.

Схожая по духу оплошность присутствует тут:

double SpectraSTPeakList::calcXCorr() {
  ....
  for (int tau = -75; tau <= 75; tau  ) {

    float dot = 0.0;
    for (unsigned int b = 0; b < numBins; b  ) {
      if (b   tau >= 0 && b   tau < (int)numBins) {
        dot  = (*m_bins)[b] * theoBins[b   tau] / 10000.0;
      }
    }
    ....
  ....
}

Диагностическое сообщение PVS-Studio: V547 Expression ‘b tau >= 0′ is always true. Unsigned type value is always >= 0. spectrastpeaklist.cpp 2058

Как видно из кода, переменная ‘tau’ принимает значения в диапазоне [-75, 75]. Дабы не выйти за рубеж массива имеется проверка: b tau >= 0. Я думаю, вы теснее осознали, что эта проверка не работает. Переменная ‘b’ имеет тип ‘unsigned’. Это значит, что и выражение «b tau» имеет тип unsigned. Значение типа unsigned неизменно огромнее либо равно 0.

8. Необычный цикл

const char* ResidueMass::getStdModResidues(....) {
  ....
  for (rmap::const_iterator i = p.first; i != p.second;   i) {
    const cResidue &r = (*i).second;
    if (r.m_masses[0].m_nterm) {
        n_term_aa_mod = true;
    } else if (r.m_masses[0].m_cterm) {
        c_term_aa_mod = true;
    }
    return r.m_residue.c_str();
  }

  if(! strcmp(mod, " N-formyl-met (Protein)")) {
    return "n";
  } if (! strcmp(mod, "13C6-15N2 (K)")) {
    return "K";
  } if (! strcmp(mod, "13C6-15N4 (R)")) {
    return "R";
  ....  
}

Предупреждение выданное PVS-Studio: V612 An unconditional ‘return’ within a loop. residuemass.cxx 1442

Внутри цикла есть оператор ‘return’, тот, что вызывается в любом случае. Цикл может исполнить только одну итерацию, позже чего функция завершится. Думаю, тут либо опечатка либо не хватает данные перед оператором ‘return’.

9. Дерзкие вычисления

double RTCalculator::getUsedForGradientRate() {
  if (rts_.size() > 0)
    return used_count_ / rts_.size();
  return 0.;
}

Предупреждение выданное PVS-Studio: V636 The ‘used_count_ / rts_.size()’ expression was implicitly casted from ‘int’ type to ‘double’ type. Consider utilizing an explicit type cast to avoid the loss of a fractional part. An example: double A = (double)(X) / Y;. rtcalculator.cxx 6406

Так как функция возвращает значения типа double, то умно предположить следующее.

Если переменная ‘used_count_’ равна 5, а функция rts_.size() вернет 7, то итог должен быть примерно равен 0,714. Вот только функция getUsedForGradientRate() в этом случае вернет 0.

Переменная ‘used_count_’ имеет тип int. Функция rts_.size() тоже возвращает значение типа ‘int’. Происходит целочисленное деление. Итог явствен. Он равен нулю. После этого нуль неявно приводится к типу double. Но это теснее не значимо.

Дабы поправить обстановку, дозволено написать так:

return static_cast<double>(used_count_) / rts_.size();

Схожие недостатки:

  • cgi_pep3d_xml.cxx 3203
  • cgi_pep3d_xml.cxx 3204
  • asapratiopeptideparser.cxx 4108

10. Эпохальный и мощный Copy-Paste

Функция setPepMaxProb() содержит несколько крупных однотипных блоков. Сразу чувствуется, что без методологии Copy-Paste тут не обошлось. А как итог, код содержит ошибку. Мне пришлось ДЮЖЕ крепко сократить код примера. В сокращенном варианте оплошность легко видна. В коде программы, подметить её примерно не реально. Да, это реклама инструментов статического обзора вообще, и PVS-Studio в частности.

void setPepMaxProb( bool use_nsp, bool use_fpkm, 
  bool use_joint_probs, bool compute_spectrum_cnts )
{  
  double prob = 0.0;
  double max2 = 0.0;
  double max3 = 0.0;
  double max4 = 0.0;
  double max5 = 0.0;
  double max6 = 0.0;
  double max7 = 0.0;
  ....
  if ( pep3 ) { ... if ( use_joint_probs && prob > max3 ) ... }
  ....
  if ( pep4 ) { ... if ( use_joint_probs && prob > max4 ) ... }
  ....
  if ( pep5 ) { ... if ( use_joint_probs && prob > max5 ) ... }
  ....
  if ( pep6 ) { ... if ( use_joint_probs && prob > max6 ) ... }
  ....
  if ( pep7 ) { ... if ( use_joint_probs && prob > max6 ) ... }

  ....
}

V525 The code containing the collection of similar blocks. Check items ‘max3′, ‘max4′, ‘max5′, ‘max6′, ‘max6′ in lines 4664, 4690, 4716, 4743, 4770. proteinprophet.cpp 4664

Предупреждение выданное PVS-Studio: V525 The code containing the collection of similar blocks. Check items ‘max3′, ‘max4′, ‘max5′, ‘max6′, ‘max6′ in lines 4664, 4690, 4716, 4743, 4770. proteinprophet.cpp 4664

К сожалению диагностика V525 даёт много неверных срабатываний и отнесена к третьему ярусу предупреждений. Но если не полениться их постигать, дозволено находить вот такие восхитительные баги.

11. Указатель не неизменно инициализируется

int main(int argc, char** argv) {
  ....
  ramp_fileoffset_t *pScanIndex;
  ....
  if ( (pFI=rampOpenFile(mzXmlPath_.c_str()))==NULL) {
    ....
  } else {
    ....
    pScanIndex = readIndex(pFI, indexOffset, &iAnalysisLastScan);
    ....
  }
  ....
  if (pScanIndex != NULL)
    free(pScanIndex);

  return 0;
}

Предупреждение выданное PVS-Studio: V614 Potentially uninitialized pointer ‘pScanIndex’ used. sqt2xml.cxx 476

Эта программа может в конце аварийно кончаться, если функция rampOpenFile() вернёт NULL. Не критично, но досадно.

Иная переменная, которая может оказаться не инициализированной, находится тут:

  • Potentially uninitialized pointer ‘fp_’ used. dta-xml.cpp 307

12. Нет виртуального деструктора

class DiscriminantFunction {
public:
  DiscriminantFunction(int charge);
  virtual Boolean isComputable(SearchResult* result) = 0;
  virtual double getDiscriminantScore(SearchResult* result) = 0;
  virtual void error(int charge);
protected:
  int charge_;
  double const_;
}; // class

class CometDiscrimFunction : public DiscriminantFunction;
class CruxDiscrimFunction : public DiscriminantFunction;
class InspectDiscrimFunction : public DiscriminantFunction;
.....

class DiscrimValMixtureDistr : public MixtureDistr {
  ....
  DiscriminantFunction* discrim_func_;
  ....
};

DiscrimValMixtureDistr::~DiscrimValMixtureDistr() {
  delete[] posinit_;
  delete[] neginit_;
  delete discrim_func_;
}

Предупреждение выданное PVS-Studio: V599 The virtual destructor is not present, although the ‘DiscriminantFunction’ class contains virtual functions. discrimvalmixturedistr.cxx 206

От класса DiscriminantFunction наследуется уйма классов. Скажем, преемником является класс DiscrimValMixtureDistr. Деструктор этого класса освобождает память, а, следственно, дюже желанно его вызывать. К сожалению, деструктор в классе DiscriminantFunction не объявлен виртуальным, со всеми вытекающими последствиями.

13. Различное

Дозволено обнаружить массу недочетов, которые не приведут к серьезным итогам, но их наличие в коде досадно. Есть и легко подозрительные, но не непременно ложные места. Вот одно из них:

Boolean MixtureModel::iterate(int counter) {
  ....
  if (done_[charge] < 0) {
    done_[charge];
  }
  else if (priors_[charge] > 0.0) {
    done_[charge]  = extraitrs_;
  }
  ....
}

Предупреждение выданное PVS-Studio: V607 Ownerless expression ‘done_[charge]‘. mixturemodel.cxx 1558

Что это? Недописанный код? Либо хотели подчеркнуть, что не нужно ничего делать, если выполнится условие «done_[charge] < 0»?

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

string Field::getText(....)
{
  ....
  char* pepString = new char[peplen   1];
  ....
  delete pepString;
  ....
}

Предупреждение выданное PVS-Studio: V611 The memory was allocated using ‘new T[]‘ operator but was released using the ‘delete’ operator. Consider inspecting this code. It’s probably better to use ‘delete [] pepString;’. pepxfield.cxx 1023

Тут следовало написать «delete [] pepString». Такое место вдалеке не одно:

  • cruxdiscrimvalmixturedistr.cxx 705
  • cruxdiscrimvalmixturedistr.cxx 715
  • mascotdiscrimvalmixturedistr.cxx 426
  • mascotdiscrimvalmixturedistr.cxx 550
  • mascotdiscrimvalmixturedistr.cxx 624
  • phenyxdiscrimvalmixturedistr.cxx 692
  • probiddiscrimvalmixturedistr.cxx 487
  • probiddiscrimvalmixturedistr.cxx 659
  • tandemdiscrimvalmixturedistr.cxx 731
  • tandemdiscrimvalmixturedistr.cxx 741

А вот реализация оператора “–”. Видимо он не применяется нигде. Напротив оплошность бы стремительно выявилась.

CharIndexedVectorIterator operator  (int)
{  // postincrement
  CharIndexedVectorIterator _Tmp = *this;
    m_itr;
  return (_Tmp);
}

CharIndexedVectorIterator& operator--()
{  // predecrement
    m_itr;
  return (*this);
}

Предупреждение выданное PVS-Studio: V524 It is odd that the body of ‘–’ function is fully equivalentto the body of ‘ ‘ function. charindexedvector.hpp 81

Операторы “–” и ” ” реализованы идентично. А дальше, вероятно, скопировали:

  • charindexedvector.hpp 87
  • charindexedvector.hpp 159
  • charindexedvector.hpp 165

Продолжать дальше не буду. Это не так уж всё увлекательно, да и статья затянулась. Как неизменно умоляю разработчиков, не останавливаться на правке перечисленных недоработок. Скачайте и проверьте самосильно план с поддержкой PVS-Studio. Я мог пропустить многие ошибки. Мы готовы выделить безвозмездный ключ на некоторое время.

Резюмирую

К сожалению, статья получилась путанной. Так что же хотел сказать автор? Испробую вовсе коротко повторить, какие мысли я хотел донести.

  1. Мы все огромнее используем и доверяем программам, исполняющим расчёты и моделирующие процессы.
  2. Программы крепко усложняются. Профессиональным программистам видимо, что невозможно создавать пакет численного моделирования так же, как применять программируемый калькулятор. Рост трудности ведёт к экспоненциальному росту числа ошибок [2].
  3. Получается, что физики/биологи/медики теснее не могут по-бывшему легко что-то посчитать. Невозможно игнорировать рост трудности программ и итоги неправильных вычислений в силу неполного владения языком программирования.
  4. В статье я привел доводы, что всё обстоит именно так. Первая цитата — люди применяют компьютер, как калькулятор. Вторая цитата — да, именно как калькулятор. Примеры ошибок — да, и подлинно допускают ошибок. Мои опасения обоснованы.

И что предлагается делать?

Для начала я хочу, Дабы люди начали осмысливать эту задачу. И рассказывали приятелем из смежных областей о ней. Для программистов давным-давно видимо, что рост трудности и тупые ошибки в крупных планах, легко доводят до беды. Люди же, использующие программирование легко как инструмент, не знают про это и не задумываются. И им стоит подсказать обратить на это внимание.

Параллель. Люди взяли в руку дубину и начали охотиться за зверьем. Пока они этим занимаются, оружие быстро совершенствуется. Дубина в их руках превращается в каменный молоток, потом в меч, потом в ружьё. А они по бывшему усердствуют ей легко глушить зайцев по голове. Немного того, что это неэффективно, так ещё и стало гораздо опасней (дозволено в себя выстрелить либо в коллегу). Охотники из племени «программистов» стремительно приспосабливаются. А остальным некогда. Они заняты охотой за зайцами. чай толк именно в зайцах. Нужно подсказать этим людям, что хотят они того либо нет, им нужно учиться. Так только каждому отменнее будет. Нечего ружьем махать.

Добавочные ссылки

  1. Брайан Грин «Изящная вселенная (суперструны, спрятанные размерности и искания окончательной теории. ISBN 978-5-453-00011-1 (УРСС), ISBN 978-5-397-01575-2 (Книжный дом „ЛИБРОКОМ“)
  2. Андрей Карпов. Ощущения, которые подтвердились числами. http://www.viva64.com/ru/b/0158/

Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB