Форум программистов, компьютерный форум, киберфорум
Наши страницы

#define RAII

Войти
Регистрация
Восстановить пароль
Оценить эту запись

#define RAII

Запись от greg zakharov размещена 29.09.2017 в 17:59
Метки c++

В плане написания безопасного кода практически у каждого уважающего себя программиста С++ свои тузы в рукаве: одни пишут классы обертки, другие разрабатывают целые библиотеки, - но, как известно, тузы бесполезны перед роял-флэш (в какой-то книге попадалось) или парой ударов в печень. Хотя о чем это я? А, ну да, про С++. Точнее про RAII, ведь речь то по сути о ней. Обсуждая с одним буржуином упомянутую несколькими словами через точку ранее идиому, мы сошлись во мнении недооценки макросов при написания безопасного кода. Здесь стоит пояснить о чем именно речь: не о пихании всего и вся в #define, ибо при наличии головы, прямых рук и хвоста хоть и можно писать симфонии и там, но стать после самому жертвой звукового насилия... Вообще, изначально мы отталкивались от того предположения, что #define полезна главным образом для написания каких-то концептов, в обход использования оператора goto (за использование которого в некоторых серьезных конторах попросту могут уволить, по крайней мере на это, жертвуя своей почкой, заложился буржуин). Но давайте спустимся с небес на землю, точнее от слов перейдем к действию.
Самый простой пример - использование FormatMessage с флагом FORMAT_MESSAGE_ALLOCATE_BUFFER (да, совсем забыл, что речь еще и о WinAPI). Согласен, можно взять любую другую функцию, скажем, CreateFile или CreateToolhelp32Snapshot, но суть все равно сводится к одному, так что... Ниже, пример использования FormatMessage.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <windows.h>
#include <cstdio>
 
...
 
void PrintErrMessage(void) {
  LPVOID msg;
  FormatMessage(
     FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
     NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
     (PTSTR) &msg, 0, NULL
  );
  printf("%s", (PTSTR)msg);
  LocalFree(msg); // не забываем освободить указатель
}
 
...
А теперь давайте предположим, что в коде, в некотором фрагменте, также используется LocalFree или любая другая функция, требующая освобождения ресурсов, то есть есть вероятность где-то позабыть дать вольную ресурсам. Что ж... давайте добавим немного волшебства.
C++
1
2
3
4
5
6
#define auto_free(NAME, T, FUNC, s)      \
   struct NAME {                         \
     T m_res;                            \
     NAME() : m_res(NULL) {}             \
     ~NAME() { if (m_res) FUNC(m_res); } \
   } s
Теперь нашу функцию PrintErrMessage можно переписать следующим образом:
C++
1
2
3
4
5
6
7
8
9
void PrintErrMessage(void) {
  auto_free(Buf, LPVOID, LocalFree, msg);
  FormatMessage(
     FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
     NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
     (PTSTR) &msg.m_res, 0, NULL
  );
  printf("%s", (PTSTR)msg.m_res);
}
На выходе из функции ресурсы освободятся сами. Конечно же это не чудестая таблетка, не панацея от всего и вся, но во всяком случае позволяет писать примеры кода без траты времени на создания классов и иже с ними, если решение некой задачи требуется здесь и сейчас, а доступа к собственным наработкам по части RAII нет. Пример выше - лишь капля в море возможных вариантов, но описывать прочие нет ни желания, ни мотивации ввиду того, что дискуссии с буржуном еще продолжаются.
Размещено в Без категории
Просмотров 388 Комментарии 2
Всего комментариев 2

Комментарии

  1. Старый комментарий
    Аватар для Avazart
    Думаю в данном случае нет смысла использовать RAII (тем более с макросами) ибо в данном коде не может быть исключений.
    Запись от Avazart размещена 29.09.2017 в 19:37 Avazart на форуме
    Обновил(-а) Avazart 29.09.2017 в 19:38
  2. Старый комментарий
    Аватар для Croessmah
    А еще можно использовать unique_ptr с указанным delete'ром.
    Запись от Croessmah размещена 02.10.2017 в 05:10 Croessmah вне форума
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru