Найди ошибку в программе коде

Время на прочтение
2 мин

Количество просмотров 8.6K

Игра PVS-Studio: найди ошибку в C++ коде
Авторы анализатора PVS-Studio предлагают вам проверить свою внимательность и развлечься. Попробуйте быстро отыскать баг в фрагменте исходного кода и ткнуть в него мышкой.

Анализаторы кода работают без устали и умеют находить множество ошибок, которые сложно заметить. Мы отобрали несколько фрагментов кода, в которых выявили ошибки с помощью PVS-Studio. Все фрагменты взяты из известных Open Source проектов.

Предлагаем вам посоревноваться с анализатором в прозорливости и попробовать самостоятельно найти ошибки. Вам будет предложено 10 случайно выбранных заданий. За верный ответ начисляется одно очко, если баг найден в течение 1 минуты.

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

Когда нашли ошибку, выделите её кликом мышки и нажмите кнопку «Ответ». Бывает, что в коде есть сразу несколько мест, куда вы можете «ткнуть» — и ответ зачтётся как правильный. Поясним это на примере.

case FuriHalSubGhzPreset2FSKDev476Async:
  preset_name = "FuriHalSubGhzPreset2FSKDev476Async";
  break;
  FURI_LOG_E(SUBGHZ_PARSER_TAG, "Unknown preset");
default:

Этот код взят из проекта FlipperZero. Анализатор PVS-Studio сообщает, что часть кода никогда не выполняется: V779 [CWE-561, CERT-MSC12-C] Unreachable code detected. It is possible that an error is present. subghz_i.c 44

Кто-то поспешил и использовал макрос логирования после оператора break. Или это следствие неудачного рефакторинга. В любом случае ошибка очевидна, но вот куда именно ткнуть мышкой – вопрос сложнее.

С одной стороны, в качестве ответа можно выбрать оператор break. Он расположен до макроса FURI_LOG_E и прерывает выполнение оператора switch. Значит, проблема здесь.

С другой стороны, можно выбрать макрос логирования. Ведь это недостижимый код.

Так как же быть? Очень просто. В данном случае правильным ответом будет считаться как выделенный оператор break, так и макрос FURI_LOG_E.

Думаем, правила понятны. Желаем вам удачи: начать игру.

Не забудьте, показать этот Quiz вашим коллегам! Развлекайтесь, и безбажного вам кода!

Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Andrey Karpov. PVS-Studio’s challenge: can you spot an error?.

Обложка: Найдите ошибки в следующем коде

Дан код:

unsigned int i;
for (i = 100; i >= 0; --i)
    printf("%dn", i);

В коде есть две ошибки.

Первая заключается в том, что используется тип unsigned int, который работает только со значениями, большими или равными нулю. Поэтому условие цикла for всегда будет истинно, и цикл будет выполняться бесконечно.

Корректный код, выводящий значения всех чисел от 100 до 1, должен использовать условие i > 0. Если нам на самом деле нужно вывести нулевое значение, то следует добавить дополнительный оператор printf после цикла for.

unsigned int i;
for (i = 100; i > 0; --i)
    printf("%dn", i);
printf("%dn", i);

Вторая ошибка — вместо %d следует использовать %u, поскольку мы выводим целые значения без знака.

unsigned int i;
for (i = 100; i > 0; --i)
    printf("%un", i);

Теперь этот код правильно выведет список чисел от 100 до 1, в убывающем порядке.

Разбор взят из книги Гейл Л. Макдауэлл «Cracking the Coding Interview» (есть в переводе).

Найдите ошибку в коде

Найдите ошибку в коде

12 241

17 ноября 2016 в 16:45

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

Вот сам код:

unsigned int i;
for (i = 100; i >= 0; --i)
	printf("%dn", i);

В этом коде есть две небольшие ошибки, которые вам стоит найти.

Ошибки

Первым делом, стоит обратить внимания на неправильное определения переменной i. Дело в том, что в данном случае оно является неверным. Тип unsigned int говорит о том, что значения этой переменной могут быть только цифры, при чем только положительные цифры без знака минус. Данная запись приводит к тому, что цикл будет выполняться вечно, так как условие всегда будет истинным (true). 

Корректный код состоял бы из такого условия i > 0. Он мог бы вывести все значения, кроме нуля. Цикл завершился бы и тогда мы могли бы после самого цикла прописать еще и вывод 0. К примеру, у нас бы получилось нечто вроде этого:

unsigned int i;
for (i = 100; i > 0; --i)
	printf("%dn", i);
printf("%dn", i);

Вторая ошибка намного проще и заключается в том, что мы используем %d вместо того чтобы использовать %u. Поскольку мы выводим числа без минуса, то именно так должно все быть. В итоге у нас получился вот такой код, который верно выводит значения от 100 до 1:

unsigned int i;
for (i = 100; i > 0; --i)
	printf("%un", i);

Больше интересных новостей

Добрый день Программа должна высчитывать определитель квадратной матрицы, размер которой вводится с клавиатуры, но при n > 2 программа высчитывает ее неправильно.
К примеру, для матрицы:

41 67 34
 0 69 24
78 58 62

Определитель должен равняться 60762, но программа выводит 79212.

Код программы:

#include <stdio.h>
#include <stdlib.h>
int main()
{
  int n;
  printf("Vvedite razmer n kvadratnoi matrici: ");
  scanf("%d", &n);
  int i = 0, j = 0, k = 0;
  int a[n][n], d = 1, r = 0;
  for (i = 0; i < n; i++)
  {
    for (j = 0; j < n; j++)
    {
      a[i][j] = rand() % 100;
      printf("%d ", a[i][j]);
    }
    printf("n");
  }
  if (n == 1)
  {
    d = a[0][0];
    printf("Opredelitel matrici raven - %d", d);
    return 0;
  }
  if (n == 2)
  {
    d = a[0][0] * a[1][1] - (a[1][0] * a[0][1]);
    printf("Opredelitel matrici raven - %d", d);
    return 0;
  }
  if (n > 2)
  {
    for (i = 0; i < n; i++)
    {
      for (j = 0; j < n; j++)
      {
        if (j > i)
        {
          r = a[j][i] / a[i][i];
          for (k = 0; k < n; k++) a[j][k] -= r * a[i][k];
        }
      }
    }
  }
  for(i = 0; i < n; i++) d *= a[i][i];
  printf("Opredelitel matrici raven - %d", d);
  return 0;
}

Помогите, пожалуйста, найти ошибку.

usva

0 / 0 / 0

Регистрация: 27.03.2023

Сообщений: 5

1

Найти ошибку в приложенном коде

27.03.2023, 17:57. Показов 514. Ответов 10

Метки нет (Все метки)


Студворк — интернет-сервис помощи студентам

Для каждого числа из последовательности определить, можно ли поставить внутри числа символ «/» так, чтобы получилась корректная запись даты в формате день/месяц. (без использования массивов, строк).

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
using System;
 
class Example
{
    private static bool isOK;
 
    public static int Number(int day)
    {
        const int months = 12;
        int[] days_in_month = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
        bool isOk;
        if (day < 11 || day > 3112)
        {
            isOk = false;
        }
        if (day % 10 > 0 && day / 10 <= days_in_month[day % 10 - 1])
        {
            isOk = true;
        }
        else
            isOK = false;
        if (day % 100 > 0 && day % 100 <= months && day / 100 <= days_in_month[day % 100 - 1])
        {
            isOk=true;
        }
        else
            isOK = false;
        if ((day % 10 > 0 && day / 10 <= days_in_month[day % 10 - 1]) || (day % 100 > 0 && day % 100 <= months && day / 100 <= days_in_month[day % 100 - 1]))
        {
            isOk = true;
        }
        else
            isOK = false;
        return 0;
    }
    static void Main()
    {
        int n,day;
        n = Convert.ToInt32(Console.ReadLine());
        for (int i = 0; i < n; i++)
        {
            day= Convert.ToInt32(Console.ReadLine());
            Console.WriteLine(isOK);
        }
 
    }
}



0



Programming

Эксперт

94731 / 64177 / 26122

Регистрация: 12.04.2006

Сообщений: 116,782

27.03.2023, 17:57

10

2106 / 1980 / 447

Регистрация: 17.02.2019

Сообщений: 3,178

27.03.2023, 18:12

2

usva, а что за ошибка?



0



0 / 0 / 0

Регистрация: 27.03.2023

Сообщений: 5

27.03.2023, 18:15

 [ТС]

3

В строке 39 (n = Convert.ToInt32(Console.ReadLine()); пишет
Исключение не обработано
System.FormatException: «Input string was not in a correct format.»



0



2106 / 1980 / 447

Регистрация: 17.02.2019

Сообщений: 3,178

27.03.2023, 18:19

4

Цитата
Сообщение от usva
Посмотреть сообщение

Исключение не обработано

наверно вводите не целое число, а что то другое

Добавлено через 34 секунды
и где у вас вызов метода Number(int day)?



0



0 / 0 / 0

Регистрация: 27.03.2023

Сообщений: 5

27.03.2023, 18:23

 [ТС]

5

Ввожу целые числа. Подскажите, пожалуйста, а как реализовать вызов метода? Я на С# вообще не программировал, просто дали задание, поэтому не все получается реализовывать.



0



293 / 202 / 49

Регистрация: 12.04.2020

Сообщений: 1,035

27.03.2023, 18:56

6

Цитата
Сообщение от usva
Посмотреть сообщение

Я на С# вообще не программировал, просто дали задание

а как дали задание если вас не научили на шарпе писать?



0



January29

2106 / 1980 / 447

Регистрация: 17.02.2019

Сообщений: 3,178

27.03.2023, 19:04

7

Лучший ответ Сообщение было отмечено usva как решение

Решение

Цитата
Сообщение от usva
Посмотреть сообщение

а как реализовать вызов метода?

метод вставлять в Main()
только зачем возвращать ноль, наверно надо значение isOK

C#
1
int Название_Вашей_Переменной = Number(day); // но в переменной day должно быть значение

и вот еще, вы объявили переменную bool isOK; запомните где маленькие и большие буковки.
Потом вы опять в методе объявили переменную bool isOk; буковка k уже маленькая.
Зачем вам две переменные если выводить будете одну которая isOK, где K уже большая.
Удалите её и замените все isOk на isOK.

Добавлено через 3 минуты
типа такого

код

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
private static bool isOK;
 
public static bool Number(int day)
{
    const int months = 12;
    int[] days_in_month = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    //bool isOk;
    if (day < 11 || day > 3112)
    {
        isOK = false;
    }
    if (day % 10 > 0 && day / 10 <= days_in_month[day % 10 - 1])
    {
        isOK = true;
    }
    else
        isOK = false;
    if (day % 100 > 0 && day % 100 <= months && day / 100 <= days_in_month[day % 100 - 1])
    {
        isOK = true;
    }
    else
        isOK = false;
    if ((day % 10 > 0 && day / 10 <= days_in_month[day % 10 - 1]) || (day % 100 > 0 && day % 100 <= months && day / 100 <= days_in_month[day % 100 - 1]))
    {
        isOK = true;
    }
    else
        isOK = false;
    return isOK;
}
static void Main()
{
    int n, day;
    n = Convert.ToInt32(Console.ReadLine());
    for (int i = 0; i < n; i++)
    {
        day = Convert.ToInt32(Console.ReadLine());
        Console.WriteLine(Number(day)); // Console.WriteLine(isOK);
    }
}



0



2629 / 1597 / 852

Регистрация: 23.02.2019

Сообщений: 3,876

27.03.2023, 19:09

8

Цитата
Сообщение от usva
Посмотреть сообщение

без использования массивов

А у вас массив есть.



0



0 / 0 / 0

Регистрация: 27.03.2023

Сообщений: 5

27.03.2023, 20:14

 [ТС]

9

Исправил все недочеты, как в вашем коде, все равно выдает ту же ошибку

Добавлено через 56 секунд
Да, есть массивы на входе, но к сожалению пока не придумал как реализовать без них

Добавлено через 1 минуту
Дали задание написать программы на нескольких ЯП



0



January29

2106 / 1980 / 447

Регистрация: 17.02.2019

Сообщений: 3,178

27.03.2023, 21:11

10

Цитата
Сообщение от usva
Посмотреть сообщение

все равно выдает ту же ошибку

ну не знаю все у меня вводится без ошибок, вы наверно не то вводите или нажимаете Enter без ввода чисел. Лучше я думаю запрос делать что вводить, ну и можно конечно проверку провернуть.

Код

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
static void Main()
{
    int n, day;
    while (true) // пока не будет введено число
    {
        Console.Write("Введите n "); // выводим запрос что вводить
        if (int.TryParse(Console.ReadLine(), out n)) // проверка на число
            break; // если число то выход из While
        Console.WriteLine("Ошибочка, введите число n "); // а если нет, то выводим ошибку с пояснением и опять заново
    }
    for (int i = 0; i < n; i++)
    {
        while (true) // также и тут
        {
            Console .Write("Введите day ");
            if (int.TryParse(Console.ReadLine(), out day))
                break;
            Console.WriteLine("Ошибочка, введите число day ");
        }
        Console.WriteLine(Number(day));
    }
}

я вот только не пойму, зачем переменную day вводить в цикле for. Так просто спросил.



0



0 / 0 / 0

Регистрация: 27.03.2023

Сообщений: 5

28.03.2023, 07:00

 [ТС]

11

Большое спасибо, разобрался, все работает



0



Понравилась статья? Поделить с друзьями:
  • Найди ошибку в программе program имя var
  • Найди ошибку в цепи питания растение волк
  • Найди ошибку в цепи питания и исправь ее
  • Найди ошибку в формуле площадей
  • Найди ошибку в фонетическом разборе ручьи