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

Как можно обрабатывать краш программы?

17.06.2025, 11:08. Показов 3542. Ответов 45

Студворк — интернет-сервис помощи студентам
Всем привет. Возник такой вопрос, допустим есть программа на c++ для винды, иногда она может крашется ошибка чтения памяти, необработанные исключения, наверное, что то еще может быть. Так вот какие есть практики быстро отлавливать и править такие истории?

1. Можно использовать логи, не всегда помогают
2. Можно использовать дебаггер, для этого нужен дамп памяти с ошибкой
3. Тестирование, ну, это понятно

Используете ли вы общий try catch в main, чтобы отлавливать все исключения и записывать их в логи(файлы, Event Viewer)?
Оправдано ли вообще делать дампы при ошибке на уровне программы?
Что еще посоветовать можете?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
17.06.2025, 11:08
Ответы с готовыми решениями:

Подскажите как убрать краш программы
Здравствуйте! В общем дана задача: Написть приложение , которое "угадывает"задуманное...

Краш программы
Из за чего крашит мою программу в 1 запросе я ввожу: C:\test.. во 2 запросе я ввожу: ...

QML SetSource() краш программы
Добрый день при запуске программы я запускаю QML с шаблоном login.qml а потом хочу показать...

45
Злостный нарушитель
 Аватар для Verevkin
10299 / 5722 / 1268
Регистрация: 12.03.2015
Сообщений: 26,497
17.06.2025, 11:25
Для локализации таких ошибок мне хватает ассёртов, грамотно расставленных по исходнику.
0
Модератор
Эксперт Java
 Аватар для alecss131
2856 / 1363 / 406
Регистрация: 11.08.2017
Сообщений: 4,348
Записей в блоге: 2
17.06.2025, 11:47
Далеко не все краши можно отловить с помощью try-catch это не языки по типу java/c#, где все ошибки можно отловить.
0
2734 / 888 / 331
Регистрация: 10.02.2018
Сообщений: 2,100
17.06.2025, 17:46
Цитата Сообщение от Arqlem Посмотреть сообщение
Так вот какие есть практики быстро отлавливать и править такие истории?
Всё что можно быстро отловить, быстро исправляется. Для этого достаточно стандартных дампов и отладчика. Всё что остаётся после этого, отлавливается медленно и мучительно с помощью логов и нестандартных подходов.

Используете ли вы общий try catch в main, чтобы отлавливать все исключения и записывать их в логи?
Нет.

Оправдано ли вообще делать дампы при ошибке на уровне программы?
Не знаю. Вроде подобное больше подходит для упрощения процедуры отправки отчётов о падении разработчику, чем даёт какие-то бонусы при отладке.

Что еще посоветовать можете?
Есть ещё разные анализаторы и профайлеры, которые могут помочь найти проблемы в коде. Что-то из них может показать потенциальные ошибки анализируя код, что-то указать на места повышенного потребления ЦПУ, а что-то подскажет про утечки памяти. Есть ещё ИИ, говорят он может поискать ошибки в вашем коде, но это не точно.
0
 Аватар для Наталья8
523 / 373 / 66
Регистрация: 09.03.2016
Сообщений: 3,959
18.06.2025, 03:22
Создаём листбокс....
C++
1
2
3
4
hwnd = CreateWindowEx(0, TEXT("listbox"), TEXT(""),
 WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | WS_TABSTOP | LBS_NOTIFY, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                CW_USEDEFAULT, hWnd, (HMENU)(UINT_PTR)IDC_LISTBOX1, lpCreateStruct->hInstance, NULL);
                      if (!hwnd) err("ListBox не создался");



делаем ему ---->> SendMessage(GetDlgItem(hWnd, IDC_LISTBOX1), LB_RESETCONTENT, 0, 0);
И заполняем 455 адресами ...

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
//------------------------------ 
    std::ifstream fin(buf); 
unsigned int line_cout; // Посчитаем строки в файле hWnd, IDC_LISTBOX1,
    if (fin.is_open()) {
        
        SendMessage(GetDlgItem(hWnd, IDC_LISTBOX1), LB_RESETCONTENT, 0, 0);
 
        short iter{};// Количество чтений файла в режиме фильтров
        if (filtr)iter = ex_clude.size();
    else {// Сколько раз читать файл? (Вывод сортированных адресов.)
        iter = 1; 
        }
        for (short read_count = 0; read_count < iter; read_count++)//Количество чтений текста.(Цикл чтений)
        {
        wchar_t buf_sample[BUFSIZ] = {},
            *sample = &buf_sample[0];
            short num{};// Считать строчки без линков, которые между линками(wchar_t*)ex_clude[i].c_str()
            line_cout = 0; // Посчитаем строки в файле
            std::string line;
fin.seekg(0, fin.beg);
 
bool no_matches{ false };// Были ли вообще строки совпадения с этим словом.
short indx_head{};// Индекс последней строчки определяющей слово для совпадений(Для удаления)
if (filtr ) {// Готовим строку в промежуток между выводом по доменам
    wchar_t mess[96]{ L"----------- " };
    wcscat(mess, (wchar_t*)ex_clude[read_count].c_str());
indx_head = SendDlgItemMessage(hWnd, IDC_LISTBOX1, LB_ADDSTRING, (WPARAM)0, (LPARAM)mess);// Вставляем...
    fnd_mask = (wchar_t*)ex_clude[read_count].c_str();// Привинтим указатель к вектору.
}
 
while (getline(fin, line))// =============== Читаем текст ===============
            {
            bool repeat(false); ++line_cout;
                //------------------------------
                char *cut_ptr = &line[0];
                if (*(cut_ptr + 4) == '-' && *(cut_ptr + 35) == '.' && *(cut_ptr + 40) == '0' && *(cut_ptr + 43) == ' ')
                {//Определяем строчку с датой с начала строки
                    memset(d_t, 0, 25);
                    for (int i = 33; i < 43; ++i)strncat(d_t, (const char*)cut_ptr + i, 1);
                    strncat(d_t, " ", 1);
                    ++num;// Строчки считает....
                }
Вот двенадцать раз ПЕРЕзаполняеться.
Утечка памяти мегабайта четыре.... И делаеться вот такое...
0
 Аватар для Наталья8
523 / 373 / 66
Регистрация: 09.03.2016
Сообщений: 3,959
18.06.2025, 03:28
Verevkin,
Куда ассёрт вставить?
0
Злостный нарушитель
 Аватар для Verevkin
10299 / 5722 / 1268
Регистрация: 12.03.2015
Сообщений: 26,497
18.06.2025, 08:04
Цитата Сообщение от Наталья8 Посмотреть сообщение
Куда ассёрт вставить?
Невозможно в такой постановке вопроса на это ответить. Если обобщённо – в те места, где возможно недопустимое значение переменной и/или входного параметра функции.
Примеры:
C++
1
2
3
4
5
6
7
8
9
// кол-во элементов массива, больших обоих своих соседей
size_t foo(int* x, size_t count)
{
  assert(x && count);
  size_t total = 0;
  for (auto p = x + 1, e = x + count - 1; p < e; p++)
    if (*(p - 1) < *p && *p > *(p + 1)) total++, p++;
  return total;
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// извлечение минора вычёркиванием верхней строки и j-го столбца
int** extract_minor(int** a, size_t n, size_t j)
{
  assert(a && n > 1);
  int** m = new int*[n - 1];
  for (auto row = 1; row != n; row++)
  {
    m[row - 1] = new int[n - 1];
    for (auto col = 0, idx = 0; col != n; col++)
      if (col != j)
        m[row - 1][idx++] = a[row][col];
  }
  return m;
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
bool can_move(int **m, const point size, const point p, const int current_priority)
{
  switch (current_priority)
  {
    case PR_RIGHT: return p.col + 1 < size.col && !m[p.row][p.col + 1]; // вправо
    case PR_UP:    return p.row > 0 && !m[p.row - 1][p.col];            // вверх
    case PR_LEFT:  return p.col > 0 && !m[p.row][p.col - 1];            // влево
    case PR_DOWN:  return p.row + 1 < size.row && !m[p.row + 1][p.col]; // вниз
    default: assert(false);
  } // switch
 
  return false;
}
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
// шаг заполнения
bool turn(int **m, const point size, point &p, int &priority, const int step)
{
  assert(size.row > 0 && size.col > 0);
  assert(0 <= p.row && p.row < size.row);
  assert(0 <= p.col && p.col < size.col);
  bool success = false;
  // static int priority; // вправо
 
  if (!m[p.row][p.col]) // не занято - сразу на выход (для 1 шага)
  {
    m[p.row][p.col] = step;
    return true;
  }
 
  // ------------------
 
  for (int attempt = 0; !success && attempt != 4; attempt++)
  {
    success = can_move(m, size, p, priority);
    if (success)
    {
      switch (priority)
      {
        case PR_RIGHT: p.col++; break; // вправо (0)
        case PR_UP:    p.row--; break; // вверх  (1)
        case PR_LEFT:  p.col--; break; // влево  (2)
        case PR_DOWN:  p.row++; break; // вниз   (3)
        default: assert(false);
      } // switch
 
      priority = next_priority(priority);
    } // if
    else priority = previous_priority(priority);
  } // for
 
  if (success) m[p.row][p.col] = step;
  return success;
}
C++
1
2
3
4
5
6
7
8
9
10
11
// натуральный логарифм через ряд Тейлора
double lnt(double z, const double precision = 1e-12)
{
  assert(z > 0 && precision > 0);
  double x = (z - 1) / (z + 1), m = x, sum = 0;
 
  for (unsigned d = 1; fabs(m) > precision; d++)
    sum += m, m *= x * x * (2 * d - 1) / (2 * d + 1);
 
  return 2 * sum;
}
1
Эксперт функциональных языков программированияЭксперт С++
 Аватар для Royal_X
6180 / 2875 / 1042
Регистрация: 01.06.2021
Сообщений: 10,546
18.06.2025, 12:50
Verevkin, я чёт не очень доверяю assert:

The definition of the macro assert depends on another macro, NDEBUG, which is not defined by the standard library.
0
 Аватар для Наталья8
523 / 373 / 66
Регистрация: 09.03.2016
Сообщений: 3,959
18.06.2025, 12:56
Да я понимаю. Я ими не пользуюсь...
Думаю головою.
Пока получаеться. В простых случаях.
printf( я вставляю... Или вот такое
C++
1
2
3
4
5
6
7
8
9
void err(char* s)
{
    MessageBoxA(NULL, s, "Error", MB_OK | MB_ICONSTOP | MB_SETFOREGROUND | MB_SYSTEMMODAL);
    ExitProcess(0);
}
BOOL warn(wchar_t* s)
{
    return MessageBoxW(NULL, s, L"Warning", MB_OK | MB_ICONWARNING | MB_SETFOREGROUND | MB_SYSTEMMODAL);
}

C++
1
2
3
char utput[25]{};
sprintf(utput,"", , , ,);
err(utput);
Останавливает программу, и выписыват результаты.
Можно несколько переменных, и с комментариями.
0
Злостный нарушитель
 Аватар для Verevkin
10299 / 5722 / 1268
Регистрация: 12.03.2015
Сообщений: 26,497
18.06.2025, 12:58
Цитата Сообщение от Royal_X Посмотреть сообщение
я чёт не очень доверяю assert:
Имеешь полное право. Это просто инструмент, которым надо уметь пользоваться. Не умеешь - не трогай.
0
 Аватар для Наталья8
523 / 373 / 66
Регистрация: 09.03.2016
Сообщений: 3,959
18.06.2025, 13:07
if(условие){printf(); getchar();};
Вот и весь ассёрт...
(ассёрт конечно профессионально... Но грубовато как то...)
===
Жёсткое вылеталово из программы.
Может мне не надо из неё вылетать, а посмотреть пятый, шестой проход и.т.д.
0
 Аватар для Morgot
336 / 129 / 18
Регистрация: 26.12.2010
Сообщений: 501
25.06.2025, 15:52
Наталья8, как по мне, лучше писать через OutputdebugstringA и блоки типа #ifdef _DEBUG..
А так принтф тоже нормально, кто как умеет, так и делает.
Я вот исключения не люблю, там фиг поймешь что и откуда прилетает.
1
 Аватар для Наталья8
523 / 373 / 66
Регистрация: 09.03.2016
Сообщений: 3,959
26.06.2025, 01:23
В дебаг выводит, в релизе нет
(msvs 2017)
Если сверху поставить --- #define _DEBUG 1
То и в релизе выводит...

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#define debug_print(fmt, ...) \
            do { if (_DEBUG) fprintf(stderr, fmt, __VA_ARGS__); } while (0)
 
int main()
{
 
#ifdef _DEBUG
    
    debug_print("%s%d", "Hello World!\n", 10);
 
#endif
    getchar();
}
На стековерфлов вычитал....
Я обычно в релизе работаю. На дебаг не переключаюсь.
Привычка после таких глюков -- в дебаг работает, в релизе нет...
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
26.06.2025, 12:36
Цитата Сообщение от Наталья8 Посмотреть сообщение
_DEBUG
\_ _/

Добавлено через 1 минуту
Цитата Сообщение от Наталья8 Посмотреть сообщение
Может мне не надо из неё вылетать
Там где нужно "не вылетать" - std::cerr
Цитата Сообщение от Наталья8 Посмотреть сообщение
а посмотреть пятый, шестой проход и.т.д.
Интересно, на что ты будешь смотреть после UB

Добавлено через 1 минуту
Цитата Сообщение от Morgot Посмотреть сообщение
Я вот исключения не люблю, там фиг поймешь что и откуда прилетает.
А в e.what() конечно же "тишина" ?
1
 Аватар для Наталья8
523 / 373 / 66
Регистрация: 09.03.2016
Сообщений: 3,959
26.06.2025, 13:59
Цитата Сообщение от SmallEvil Посмотреть сообщение
что ты будешь смотреть после UB
Надо всё время запускать и проверять. Тогда отловишь и UB.
Бывает и UB... Кто из нас ни без греха...

Добавлено через 1 минуту
Цитата Сообщение от SmallEvil Посмотреть сообщение
_DEBUG
Такой макрос у меня в системе... Называеться так...

Добавлено через 6 минут
Макросы ?
Иногда пользую... Они зелёные такие. Люблю всё зелёное...

Добавлено через 2 минуты
Соберём тебе ещё на одну мядаль....

Добавлено через 1 минуту
Бывают же где то люди серьёзные... Не то что вы всёобсиратели.
0
 Аватар для Наталья8
523 / 373 / 66
Регистрация: 09.03.2016
Сообщений: 3,959
26.06.2025, 14:17

Если что, я на коленках не пишу. Всё проверяю.
0
Отпрыск ChatGPT
 Аватар для Azawa
33 / 29 / 4
Регистрация: 18.06.2019
Сообщений: 152
09.07.2025, 09:25
C++
1
2
3
#include <crtdbg.h>
 
#define ASSERT(expr) _ASSERTE((expr))
Потом в коде можете делать что-то вроде:
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
BOOL RegisterMyClass()
{
    BOOL bResult = FALSE;
 
    BOOL bStatus = RegisterClass(...);
    ASSERT(bStatus); // ← Покажет диалоговое окно с неудовлетворённым ASSERT
    if (!bStatus)
    {
        // Произошла ошибка в процессе выполнения функции
        // Нам нужно преждевременно завершить её выполнение и выйти из неё (возможно, тоже вернув статус что и наша функция завершилась с ошибкой)
        throw std::runtime_error(...);
        // или
        DeleteObject(...);
        return FALSE;
        // или
        goto fail;
    }
 
    // Если ошибок не произошло, мы дошли до сюда. Поэтому устанавливаем возвращаемый статус что функция выполнилась успешно.
    bResult = TRUE;
 
fail:
    // очистка ресурсов
    DeleteObject(...);
 
    return bResult;
}
 
}
...
0
фрилансер
 Аватар для Алексей1153
6454 / 5655 / 1129
Регистрация: 11.10.2019
Сообщений: 15,054
09.07.2025, 09:33
Azawa, слышал ли что-нибудь про RAII ?
0
Отпрыск ChatGPT
 Аватар для Azawa
33 / 29 / 4
Регистрация: 18.06.2019
Сообщений: 152
09.07.2025, 09:52
Более низкий уровень если нужно ловить специфичные исключения от ОС (вроде нарушения целостности памяти процесса EXCEPTION_ACCESS_VIOLATION) - это структурная обработка исключений (SEH).

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
int MyFilter(PEXCEPTION_POINTERS pExceptionInfo) {
    DWORD code = pExceptionInfo->ExceptionRecord->ExceptionCode;
 
    if (code == EXCEPTION_ACCESS_VIOLATION) {
        MessageBox(NULL, L"Всё, приехали.", NULL, MB_OK | MB_ICONERROR);
        // Здесь можно создать дамп процесса, и т.д.
        return EXCEPTION_EXECUTE_HANDLER;
    }
    else if (code == EXCEPTION_INT_DIVIDE_BY_ZERO) {
        MessageBox(NULL, L"На ноль делить нельзя!", NULL, MB_OK | MB_ICONEXCLAMATION);
        return EXCEPTION_EXECUTE_HANDLER;
    }
 
    // Для остальных исключений, передаём обработку дальше более верхнему обработчику
    return EXCEPTION_CONTINUE_SEARCH;
}
 
int main() {
    // Установить глобальный обработчик для необрабатываемых исключений. Любое исключение вне блока __try будет обрабатываться MyFilter
    SetUnhandledExceptionFilter(MyFilter);
 
    // Частный случай обработанного исключения
    __try {
        int* p = NULL;
        *p = 42; // Крашим
    }
    __except (MyFilter(GetExceptionInformation())) {
        MessageBox(NULL, L"Исключение обработано, данный случай нормален в нашем случае.", NULL, MB_OK | MB_ICONINFORMATION);
    }
 
    return 0;
}
Добавлено через 7 минут
Цитата Сообщение от Алексей1153 Посмотреть сообщение
Azawa, слышал ли что-нибудь про RAII ?
Да, знаком. Для этого есть ATL и MFC.
0
фрилансер
 Аватар для Алексей1153
6454 / 5655 / 1129
Регистрация: 11.10.2019
Сообщений: 15,054
09.07.2025, 11:33
Цитата Сообщение от Azawa Посмотреть сообщение
Для этого есть
достаточно стандартного C++
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
09.07.2025, 11:33
Помогаю со студенческими работами здесь

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

Краш программы после вызова Inverse_element
#include&lt;iostream&gt; #include&lt;math.h&gt; #include &lt;fstream&gt; #include &lt;string&gt; using namespace std;...

Краш программы
Господа, Добрый день! может быть кто-нибудь знает, где искать ошибку? Никакой код не исполняется,...

Краш программы. Поиск по структуре
Доброго времени суток, уважаемые форумчане! Я столкнулся с такой проблемой... Условие задачи : ...

Краш программы с STATUS_STACK_BUFFER_OVERRUN
Привет всем! Делаю программу, основанную на рекурсивном поиске файлов, и всё работает отлично,...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru