Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.91/11: Рейтинг темы: голосов - 11, средняя оценка - 4.91
1 / 1 / 0
Регистрация: 31.07.2022
Сообщений: 17

Игра зависает через неопределённое время жрёт процессор и выключается

31.07.2022, 15:47. Показов 2033. Ответов 12

Студворк — интернет-сервис помощи студентам
Здравствуйте, это моё первое приложение на WINAPI. Под конец столкнулся с проблемой зависания. Игра "Бомбер" запускается и работает отлично, но через несколько игр неожиданно зависает (причину не определил). Отладчик WS2019 не останавливается ни на каких исключениях. Посмотрел через Deleaker, утечек не наблюдаю.

Так как код довольно большой опишу его словами:
есть массив(map) который хранит ячейки(части) карты - class Cell. У Cell есть указатель на class Item, который является базовым для большинства элементов игры(Wall, Barrier, Void...).
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
class Cell
{
public:
    Cell();
 
    ~Cell();
 
    char get_type();
    Item* get_keep();
 
    void set(Item* keep, char type);
 
private:
    char type;
    Item* keep;
};
 
class Item {
public:
    Item() {}
 
    ~Item() {
        int a = 0;  // для отладки
    }
 
    void virtual Draw(HDC hdc, std::pair<float, float> place) {}
 
    void virtual Break(std::pair<int, int> map_cord);
};

Чтобы изменить содержимое карты используется метод Cell::set(Item*, char) :
C++
1
map[map_cord.first][map_cord.second].set(new Wall(), 'W');  // или другой класс
Ещё есть класс игрок, который не привязан к Cell, а ходит поверх карты.
Прорисовка и движения происходят по таймеру (25 мс). Для отрисовки используется двойная буферизация.

Думаю зависание как-то связано с delete в коде снизу, так как если их закоментировать, то зависания не наблюдал, но появляются утечки.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void Cell::set(Item* keep, char type)
{
    if (this->type != type) {
        if (this->keep != nullptr) {
            delete (this->keep);
        }
        this->keep = keep;
        this->type = type;
    }
    else {
        delete keep;
        keep = nullptr;
    }
}
Пожалуйста помогите решить проблему. Также приветствуются советы как лучше можно было написать код, и где узкие места.
Приведу ссылку для удобства на GitHab с полным кодом. Если нужно, то могу отправить код и сюда, это мой первый пост и я не знаю можно ли приводить ссылки когда код большой (иначе получится очень много текста).

GitHab: https://github.com/2romanio005/Domber
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
31.07.2022, 15:47
Ответы с готовыми решениями:

Hp pavilion g6 2240sr выключается через неопределенное время хаотично
Здравствуйте пользуюсь ноутбуком hp pavillion g6 2240sr , пользуюсь уже год, брал с рук мертвым... Восстановил... заменив ключи питания...

Warcraft 3 зависает через неопределённое игровое время
Ребят , я так понял , что тут головастые зависают ) помоги плиз чайнику . Описываю трабл в крации : комп виснет в игре после совершенно...

Комп зависает и через время выключается
Добрый день! Все началось с того что комп просто завис ( полностью зависла картинка на мониторе, даже мышка по экрану не двигалась). Я...

12
Заблокирован
31.07.2022, 18:09
2romanio005, в архиве сюда?
1
1 / 1 / 0
Регистрация: 31.07.2022
Сообщений: 17
31.07.2022, 18:17  [ТС]
Архив с кодом:
Вложения
Тип файла: 7z Bombers.7z (9.2 Кб, 5 просмотров)
0
2738 / 1664 / 267
Регистрация: 19.02.2010
Сообщений: 4,396
31.07.2022, 19:57
Цитата Сообщение от 2romanio005 Посмотреть сообщение
C++
1
2
3
4
    void set(Item* keep, char type);
 
private:
    char type;
Блин, ну нафига такое? Чтобы потом случайно поиметь проблему из-за очепятки при задании символа? Синтаксически код при очепятке (когда например, будет 'w' вместо 'W') останется корректным - но его семантическая правильность помрёт (если в коде затем не сделаешь обработку независимо от регистра). И не отловишь затем быстро подобную ошибку.
Делай вне класса enum с нужным числом состояний - и затем в классе поле этого перечислимого типа (вместо char). Состояния енума будут в затем в коде возникать в качестве именованных констант - поэтому все синтаксические очепятки будут сразу же ловиться компилятором.
1
1 / 1 / 0
Регистрация: 31.07.2022
Сообщений: 17
31.07.2022, 20:11  [ТС]
VTsaregorodtsev, спасибо! Согласен с вами. А можно как-нибудь обойтись вообще без этой переменной(она используется только для понимания какой именно класс лежит в указателе)?
0
фрилансер
 Аватар для Алексей1153
6465 / 5678 / 1131
Регистрация: 11.10.2019
Сообщений: 15,118
31.07.2022, 20:35
2romanio005, попробуй переписать игру, заменив сырые указатели на умные (std::unique_ptr / std::shared_ptr)

Добавлено через 1 минуту
Цитата Сообщение от 2romanio005 Посмотреть сообщение
А можно как-нибудь обойтись вообще без этой переменной(она используется только для понимания какой именно класс лежит в указателе)?
dynamic_cast в помощь

Добавлено через 1 минуту
Цитата Сообщение от VTsaregorodtsev Посмотреть сообщение
enum
тогда уж лучше enum class

Добавлено через 1 минуту
2romanio005, русские комментарии в гитхабе побились

Добавлено через 12 минут
2romanio005,

void (*ReadI)(HDC & I_, std::string way) = [](HDC& I_, std::string way) {
->

C++
1
auto ReadI = [](HDC& I_, std::string way) {
1
1 / 1 / 0
Регистрация: 31.07.2022
Сообщений: 17
31.07.2022, 21:02  [ТС]
nick]VTsaregorodtsev[/nick],
Цитата Сообщение от Алексей1153 Посмотреть сообщение
попробуй переписать игру, заменив сырые указатели на умные (std::unique_ptr / std::shared_ptr)
Спасибо за ваши ответы. Почему сырые указатели так плохи?
Я могу это сделать, но:
1) это не решит/плохо решит подобные проблемы в будущем
2) я не горю желанием уходить в абстракцию, не поняв базы
Цитата Сообщение от Алексей1153 Посмотреть сообщение
dynamic_cast в помощь
Спасибо, почитаю.
Цитата Сообщение от Алексей1153 Посмотреть сообщение
void (*ReadI)(HDC & I_, std::string way) = [](HDC& I_, std::string way) {
-> auto ReadI = [](HDC& I_, std::string way) {
Почему я должен так делать? auto - сахар, которым я не очень хочу пользоваться.
0
2735 / 890 / 331
Регистрация: 10.02.2018
Сообщений: 2,112
31.07.2022, 21:35
Лучший ответ Сообщение было отмечено 2romanio005 как решение

Решение

У меня зависло после одновременной установки нескольких бомб и взрыва одной из них. Хотя иногда подобные действия не приводят к зависаниям.

C++
1
2
3
4
5
6
void OneStep() {
    NowTime++;
 
    while (ActiveBomb.size() != 0 && (*(ActiveBomb.begin())).first <= NowTime) { //<--- зависло в этом цикле
        (*((*(ActiveBomb.begin())).second)).Detonation();
    }
Содержимое вектора ActiveBomb, первая бомба 'битая'
Code
1
2
3
4
-       ActiveBomb  { size=3 }  
+       [0] (2154, 0x0105e040 {map_cord=(-572662307, -572662307) radius=-572662307 timeout=-572662307 ...}) 
+       [1] (2181, 0x0105e598 {map_cord=(3, 3) radius=4 timeout=2181 ...})  
+       [2] (3607, 0x0105e598 {map_cord=(3, 3) radius=4 timeout=2181 ...})
C++
1
2
3
void Bomb::Detonation()
{
    if (this->IBroken) return; //<--- тут выходит из функции
Содержимое полей битого объекта 'бомба':
Code
1
2
3
4
5
6
7
-       this    
+       Item    {...}   
+       map_cord    (-572662307, -572662307)    
        radius  -572662307  
        timeout -572662307  
        IBroken true (221)  
+       creater 0xdddddddd
1
1 / 1 / 0
Регистрация: 31.07.2022
Сообщений: 17
31.07.2022, 22:01  [ТС]
Ygg, Спасибо! Скорее всего из ActiveBomb удаляется не та бомба (хотя странно), завтра буду тестить!
0
фрилансер
 Аватар для Алексей1153
6465 / 5678 / 1131
Регистрация: 11.10.2019
Сообщений: 15,118
31.07.2022, 22:44
Цитата Сообщение от 2romanio005 Посмотреть сообщение
1) это не решит/плохо решит подобные проблемы в будущем
почему ? От сырых указателей поиметь проблем намного легче.
Но, впрочем, ошибка может быть и не из-за лапши с указателями

Цитата Сообщение от 2romanio005 Посмотреть сообщение
Почему я должен так делать? auto - сахар, которым я не очень хочу пользоваться.
не должен, конечно же. Придумывай каждый раз и пиши вручную тип-простыню по 5 минут

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

C++
1
2
3
4
5
6
7
8
9
    //ok
    void(*f1)()=[]()
    {
    };
    
    //error
    void(*f2)()=[&]()
    {
    };
0
Заблокирован
01.08.2022, 07:34
2romanio005, если закомментить delete[] ... и зависание исчезнет, видимо выходите за границы массива при его использовании
0
1 / 1 / 0
Регистрация: 31.07.2022
Сообщений: 17
01.08.2022, 14:02  [ТС]
Ygg, Всё оказалось довольно просто, как обычно. В сете ActiveBomb хранились все активные бомбы, чтобы отслеживать какая взорвётся первой. И я не очищал этот контейнер когда начиналась новая игра, в нём оставались указатели на удалённые Bomb с предыдущей игры. После этого всё зависало. Если же я убирал delete в Cell::set() то ActiveBomb хранил в себе указатели на не удалённые бомбы, что не вызывало зависаний, но вызывало неправильную работу кода(различные баги) ну и появлялись утечки.
Всем большое спасибо, и хорошего настроения!
1
фрилансер
 Аватар для Алексей1153
6465 / 5678 / 1131
Регистрация: 11.10.2019
Сообщений: 15,118
01.08.2022, 14:12
2romanio005,
Цитата Сообщение от 2romanio005 Посмотреть сообщение
1) это не решит/плохо решит подобные проблемы в будущем
я угадал, значит
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
01.08.2022, 14:12
Помогаю со студенческими работами здесь

Замирает тачпад через неопределенное время (Linux Mint)
У меня ноут от DNS На нем сейчас стоит Linux Mint (Linux 3.16.0-36-generic #48~14.04.1-Ubuntu) Если подключаю мышку, то все в порядке...

Через неопределенное время в браузере Chrome открывается новая вкладка с рекламой
Здравствуйте. Столкнулся с такой проблемой - скачал файл, после чего на компьютер были установлены браузер Амиго, Мейл.ру, Яндекс, ВК. Все...

Поменял процессор с intel pentium e2160 на d945 , но во время загрузки БИОС комп выключается
Здравствуйте.Так вот,мать стоит ESC 945gct-m2.Что делать не знаю,а сделать хотелось бы. Биос стоит American Megatrends version...

Во время игры монитор гаснет на несколько секунд, после включения игра зависает и закрывается
Добрый день, докупил оперативки в свой комп и поменял видеокарту на Radeon RX 560 - 4 гб, после этого как только начинаю играть в какую...

Через некоторое время выключается ПК
Случилась такая проблема,установил новую мать,на ней 4 слота под DDR3,установил все 4 слота оперативкой,включил компьютер,он работает,но...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru