Читаем Программирование. Принципы и практика использования C++ Исправленное издание полностью

Здесь содержатся три очевидные ошибки. (Какие именно?) Кроме того, хороший тестировщик немедленно выявит возможности для переполнения при добавлении чисел к переменной sum.

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

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

char buf[MAX];    // буфер фиксированного объема

char* read_line // опасная функция

{

  int i = 0;

  char ch;

  while(cin.get(ch) && ch!='\n') buf[i++] = ch;

  buf[i+1] = 0;

  return buf;

}

Разумеется, вы не написали бы ничего подобного! (А почему нет? Что плохого в функции read_line?) Однако эта ошибка, к сожалению, является довольно распространенной и имеет разные варианты.

// опасный фрагмент

gets(buf);       // считываем строку в переменную buf

scanf("%s",buf); // считываем строку в переменную buf

  Поищите описание функций gets и scanf в своей документации и избегайте их как чумы. Под словом “опасная” мы понимаем, что переполнение буфера является инструментом для взлома компьютеров. В настоящее время реализации выдают предупреждение об опасности использования функции gets и ее аналогов.

<p id="AutBody_Root521"><strong>26.3.3.4. Ветвление</strong></p>

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

• Все ли возможные варианты предусмотрены?

• Правильные ли действия связаны с правильными вариантами выбора?

Рассмотрим следующую бессмысленную функцию:

void do_branch1(int x, int y) // плохая функция

    // неправильное использование инструкции if

{

  if (x<0) {

    if (y<0)

      cout << "Большое отрицательное число \n";

    else

      cout << "Отрицательное число \n";

  }

  else if (x>0) {

    if (y<0)

      cout << "Большое положительное число \n";

    else

      cout << "Положительное число \n";

  }

}

Наиболее очевидная ошибка в этом фрагменте заключается в том, что мы забыли о варианте, в котором переменная x равна нулю. Сравнивая числа (положительные или отрицательные) с нулем, программисты часто забывают о нем или приписывают неправильной ветви (например, относят его к отрицательным числам). Кроме того, существует более тонкая (хотя и распространенная) ошибка, скрытая в этом фрагменте: действия при условиях (x>0 && y<0) и (x>0 && y>=0) каким-то образом поменялись местами. Это часто случается, когда программисты пользуются командами “копировать и вставить”.

Чем более сложными являются варианты использования инструкций if, тем вероятнее становятся ошибки. Тестировщики анализируют такие коды и стараются не пропустить ни одной ветви. Для функции do_branch1 набор тестов очевиден.

do_branch1(–1,–1);

do_branch1(–1, 1);

do_branch1(1,–1);

do_branch1(1,1);

do_branch1(–1,0);

do_branch1(0,–1);

do_branch1(1,0);

do_branch1(0,1);

do_branch1(0,0);

По существу, это наивный подход “перебора всех альтернатив”, которой мы применили, заметив, что функция do_branch1 сравнивает значения с нулем с помощью операторов < и >. Для того чтобы выявить неправильные действия при положительных значениях переменной x, мы должны объединить вызовы функции с желаемыми результатами.

Обработка инструкций switch аналогична обработке инструкций if.

void do_branch1(int x, int y)  // плохая функция

 // неправильное использование инструкции switch

{

  if (y<0 && y<=3)

  switch (x) {

  case 1:

    cout << "Один\n";

    break;

  case 2:

    cout << "Два\n";

    case 3:

  cout << "Три\n";

  }

}

Здесь сделаны четыре классические ошибки.

• Мы проверяем значения неправильной переменной (y, а не x).

• Мы забыли об инструкции break, что приводит к неправильному действию при x==2.

• Мы забыли о разделе default (считая, что он предусмотрен инструкцией if).

• Мы написали y<0, хотя имели в виду 0.

Перейти на страницу:

Похожие книги

97 этюдов для архитекторов программных систем
97 этюдов для архитекторов программных систем

Успешная карьера архитектора программного обеспечения требует хорошего владения как технической, так и деловой сторонами вопросов, связанных с проектированием архитектуры. В этой необычной книге ведущие архитекторы ПО со всего света обсуждают важные принципы разработки, выходящие далеко за пределы чисто технических вопросов.?Архитектор ПО выполняет роль посредника между командой разработчиков и бизнес-руководством компании, поэтому чтобы добиться успеха в этой профессии, необходимо не только овладеть различными технологиями, но и обеспечить работу над проектом в соответствии с бизнес-целями. В книге более 50 архитекторов рассказывают о том, что считают самым важным в своей работе, дают советы, как организовать общение с другими участниками проекта, как снизить сложность архитектуры, как оказывать поддержку разработчикам. Они щедро делятся множеством полезных идей и приемов, которые вынесли из своего многолетнего опыта. Авторы надеются, что книга станет источником вдохновения и руководством к действию для многих профессиональных программистов.

Билл де Ора , Майкл Хайгард , Нил Форд

Программирование, программы, базы данных / Базы данных / Программирование / Книги по IT
Программирование. Принципы и практика использования C++ Исправленное издание
Программирование. Принципы и практика использования C++ Исправленное издание

Специальное издание самой читаемой и содержащей наиболее достоверные сведения книги по C++. Книга написана Бьярне Страуструпом — автором языка программирования C++ — и является каноническим изложением возможностей этого языка. Помимо подробного описания собственно языка, на страницах книги вы найдете доказавшие свою эффективность подходы к решению разнообразных задач проектирования и программирования. Многочисленные примеры демонстрируют как хороший стиль программирования на С-совместимом ядре C++, так и современный -ориентированный подход к созданию программных продуктов. Третье издание бестселлера было существенно переработано автором. Результатом этой переработки стала большая доступность книги для новичков. В то же время, текст обогатился сведениями и методиками программирования, которые могут оказаться полезными даже для многоопытных специалистов по C++. Не обойдены вниманием и нововведения языка: стандартная библиотека шаблонов (STL), пространства имен (namespaces), механизм идентификации типов во время выполнения (RTTI), явные приведения типов (cast-операторы) и другие. Настоящее специальное издание отличается от третьего добавлением двух новых приложений (посвященных локализации и безопасной обработке исключений средствами стандартной библиотеки), довольно многочисленными уточнениями в остальном тексте, а также исправлением множества опечаток. Книга адресована программистам, использующим в своей повседневной работе C++. Она также будет полезна преподавателям, студентам и всем, кто хочет ознакомиться с описанием языка «из первых рук».

Бьерн Страуструп , Бьёрн Страуструп , Валерий Федорович Альмухаметов , Ирина Сергеевна Козлова

Программирование, программы, базы данных / Базы данных / Программирование / Учебная и научная литература / Образование и наука / Книги по IT