I am trying to write a DriverIterator class to iterate over all the volumes in my comuter.
I understand the next class can cause a memory leak since:
current_ = std::make_unique<Driver>(paths);
can throw an exception (for some reason..) and therefore the construction will not be finished, and as a result destructor will not be invokek and the handle will not be closed properly.
As I undesrtand, once I receive the handle, I should stop constructing. But how can I achieve that? FindFirstVolumeW also provides me data that I need to use before constructor is finished.
DriverIterator.hpp:
class DriverIterator final
{
public:
explicit DriverIterator();
~DriverIterator();
private:
std::unique_ptr<Driver> current_;
bool is_empty_;
HANDLE handle_;
public:
bool is_empty() const;
Driver get_current() const;
void next();
private:
HANDLE start_find();
public:
DriverIterator(const DriverIterator&) = delete;
DriverIterator(DriverIterator&&) = delete;
DriverIterator& operator=(const DriverIterator&) = delete;
DriverIterator& operator=(DriverIterator&&) = delete;
};
DriverIterator.cpp:
DriverIterator::DriverIterator():
handle_(start_find())
{}
DriverIterator::~DriverIterator()
{
try
{
FindVolumeClose(handle_);
}
catch (...)
{
}
}
HANDLE DriverIterator::start_find()
{
static constexpr uint32_t MAX_BUFFER_SIZE = 1024;
wchar_t buffer[MAX_BUFFER_SIZE];
HANDLE handle = FindFirstVolumeW(buffer, MAX_BUFFER_SIZE);
if (handle == INVALID_HANDLE_VALUE)
{
//throw exception
}
wchar_t paths[1024];
DWORD res_size;
if (!GetVolumePathNamesForVolumeNameW(buffer, paths, 1024, &res_size))
{
//throw exception
}
current_ = std::make_unique<Driver>(paths);
is_empty_ = false;
return handle;
}
bool DriverIterator::is_empty() const
{
return is_empty_;
}
Driver DriverIterator::get_current() const
{
if (is_empty_)
{
//throw exception
}
return *current_;
}
void DriverIterator::next()
{
//code...
}