Как обеспечить и принудительно владеть дескриптором для предотвращения нежелательных вызовов CloseHandle? - PullRequest
0 голосов
/ 08 октября 2018

TL; DR

Скажем, я реализую класс, который реализует API, который возвращает HANDLE.Скажем, мой класс является владельцем HANDLE и несет ответственность за его создание, обновление и закрытие.

Как запретить вызывающим программам моего API закрывать мой дескриптор и нарушать мой дизайн?

BACKGROUND

CreateToolhelp32Snapshot - это дорогостоящий вызов, и его следует использовать с умом.У меня много проектов в моем решении, и каждый из них небрежно вызывает CreateToolhelp32Snapshot.

Я хочу реализовать класс-обертку, который обеспечивает «умный» доступ к CreateToolhelp32Snapshot.

Мой класс будет владельцем HADNLE, возвращаемого CreateToolhelp32Snapshot, и обновит его(повторно вызывайте CreateToolhelp32Snapshot), когда это необходимо (еще не полностью определите, когда это необходимо).

Для простоты давайте предположим, что мое приложение представляет собой один процесс и поток, а мой класс имеет только один экземпляр.

Ответы [ 4 ]

0 голосов
/ 09 октября 2018

Если бы я реализовал этот класс, я просто написал бы метод Enumerate и вызвал бы CreateToolhelp32Snapshot, другой набор функций, а затем CloseHandle.HANDLE не будет частью самого класса, но будет локальным для метода Enumerate.Перечисление будет заполнять требуемую структуру (определяемую пользователем) и создаст vector этой структуры (или (unordered_) map, если требуется какой-либо доступ PID -> ProcessInformation.).Этот класс будет облегчать методы для получения этих перечисляемых данных.Для класса C ++ первого класса я бы на самом деле реализовал методы begin и end, чтобы класс / объект можно было использовать с основанным на диапазоне циклом for.

Зачем вам действительно нужно задержка в фактической обработке CreateToolhelp32Snapshot?К тому времени, когда подлинный вызывающий вызов вызовет некоторый безопасный Win32 API для этого дескриптора, состояние запущенных процессов изменилось бы.Если объект вашего класса остается надолго (er), то все, что вы имеете, это устаревшая / противоречивая информация по этому дескриптору.

0 голосов
/ 08 октября 2018

Вы не можете.Пока вы не желаете полностью инкапсулировать все варианты использования HANDLE, внешний код, который может напрямую обращаться к HANDLE, может его закрыть.Это ничем не отличается от способности delete smart_ptr.get();.

C ++ защитить вас от случайного неправильного использования.Он не может защитить вас от коварства .Если пользователь, использующий класс smart-handle, не получил напоминание о том, что класс smart-handle является владельцем HANDLE, вы мало что можете сделать.

0 голосов
/ 08 октября 2018

Что вы можете сделать, это использовать DuplicateHandle, а требует , чтобы вызывающая сторона вызывала CloseHandle.Кроме этого вы должны доверять звонящему.

0 голосов
/ 08 октября 2018

Скажем, я реализую класс, который реализует API, который возвращает HANDLE

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

class snapshot
{
    public:
    snapshot()
    {
        m_handle = CreateToolhelp32Snapshot(...);
    }
    ~snapshot()
    {
        CloseHandle(m_handle);
    }
    getModules()
    {
        // use m_handle to return a list of modules.
    }
    private:
    HANDLE m_handle;
};
...