Похожие презентации:
Управление ресурсами
1. Управление ресурсами
2.
Ресурс – это физический или виртуальный компоненткомпьютерной системы, обладающий свойством
ограниченности.
(©Wikipedia)
3. Физические ресурсы
ПроцессорОперативная память
Жесткий диск
Сетевой адаптер
Видеокарта
Звуковая карта
Устройства ввода/вывода (клавиатура, мышь, принтер, сканер и т.п.)
4. Виртуальные ресурсы
Виртуальная памятьФайлы
Сокеты
Объекты синхронизации (мьютекс, критическая секция, семафор и т.п.)
Объекты межпроцессного взаимодействия (pipes, mapped files, mailslots и
т.п.)
Аттрибуты безопасности, дескрипторы объектов ОС и т.п.
5. C++ storage duration categories
1.Static – глобальные переменные, статические локальные переменные, статические
члены классов. Создаются при запуске приложения и разрушаются при выходе.
2.
Thread storage (C++ 11) – переменные, доступные только в потоке (обозначаются
ключевым словом thread_local). Создаются при старте потока, разрушаются при
завершении его работы.
3.
Automatic – локальные переменные. Разрушаются на выходе из блока, в котором они
созданы.
4.
Dynamic – создаются при помощи операторов new и разрушаются при помощи
операторов delete.
6. Объекты с автоматической продолжительностью хранения
Преимущества:1. Быстрое выделение памяти.
2. Объекты на стеке автоматически разрушаются при выходе из области видимости.
Недостатки:
1. Размер стека ограничен (по умолчанию в Visual C++ 1Mb для каждого потока).
2. Нужно знать размер объекта на этапе компиляции.
3. Стеком сложнее управлять.
7. Специальные методы классов
1. Версии конструкторов копирования и операторов присваивания, генерируемыекомпилятором, осуществляют “shallow copy” членов. Необходимо переопределять их, если
такое поведение неверно.
class Test {
int* m_data;
Test(const Test& other) {
m_data = new int(*other.m_data);
}
};
8. Специальные методы классов
2. Проверяйте в операторе присваивание случай самоприсваивания:Test& operator=(const Test& other) {
if (this != &other) {
delete m_data;
m_data = new int(*other.m_data);
}
return *this;
}
9. Общая схема работы с ресурсами
1. Захватить ресурс (open, create, allocate, attach)2. Использовать ресурс
3. Освободить ресурс (close, free, delete, detach)
Внимание:
1. Если операция захвата ресурса возвращает статус
успешности, всегда проверяйте его.
2. Используйте правильную операцию для освобождения
ресурса
10. Захват ресурса без освобождения
class Singleton{
static Singleton& get()
{
static Singleton instance;
return instance;
}
};
class Log {
void Flush();
~Log() { Flush() };
vector<string> buffer;
};
int main() {
Log *log = new Log();
...
return 0;
}
11. “Ручное” управление ресурсами
void f() {Test *test = new Test;
DoSomething(test);
delete test;
}
CRITICAL_SECTION cs;
void do_work()
{
::EnterCriticalSection(&cs);
f();
::LeaveCriticalSection(&cs);
}
void f()
{
throw runtime_error(“err”);
}
bool f() {
Test *tst = new Test;
…
// Fixed issue #12
if (!CheckSome()) {
return false;
}
…
test->Action();
delete test;
return true;
}
12. Stack unwinding
void func(){
string s1{ "test" };
vector<int> v1{ 1, 4, 5 };
throw runtime_error("");
}
class Test {
public:
~Test()
{
throw std::runtime_error("");
// DON’T DO IT!!!
}
};
void f() {
std::string s1{ "str" };
Test test;
throw std::runtime_error("");
}
13. Использование RAII (guards)
class SocketGuard {public:
SocketGuard(SOCKET sock_) :
sock_ (sock) {}
operator SOCKET()
{
return sock_;
}
~ SocketGuard()
{
::closesocket(sock_);
}
private:
SOCKET sock_;
};
void f()
{
SOCKET sock = ::socket(…);
if (sock != INVALID_SOCKET)
{
SocketGuard guard(sock);
::connect(guard, …);
}
}
14. std::auto_ptr
class Test{
};
void f()
{
std::auto_ptr<Test> p(new Test);
...
}
void f()
{
std::auto_ptr<Test> p1(new Test);
...
std::auto_ptr<Test> p2 = p1;
}
// Unsafe, don't do it!!!
std::vector<std::auto_ptr<int>> vec;
15. std::auto_ptr
Недостатки:1. Не может использоваться в контейнерах STL.
2. Не может быть использован с new[].
3. Неочевидная передача владения (при копировании и передаче в
качестве параметра функции по значению).
4. Нельзя использовать с другими типами ресурсов, отличными от памяти.
16. std::unique_ptr
template<typename T, typename D =default_delete<T>>
class unique_ptr
{
typedef ... pointer;
typedef T element_type;
typedef D deleter_type;
};
// Specialization for arrays
template<typename T[], typename D>
class unique_ptr
{
typedef ... pointer;
typedef T element_type;
typedef D deleter_type;
};
17. std::unique_ptr
unique_ptr<int> p1{ new int(10) };//Error: assignment operator is deleted
unique_ptr<int> p2 = p1;
// Correct
unique_ptr<int> p2 = std::move(p1);
// Array
unique_ptr<int[]> p{ new int[10] };
// In container
vector<unique_ptr<int>> vec;
18. std::unique_ptr
void del(void* data){VirtualFree(data, 0, MEM_RELEASE);
}
void *pData = VirtualAlloc(
nullptr,
0x4000,
MEM_COMMIT,
PAGE_READWRITE);
unique_ptr<void,decltype(&del)> p(
pData, del);
auto del = [](void *data)
{
VirtualFree(data, 0, MEM_RELEASE);
};
unique_ptr<void,decltype(del)> p(
pData, del);
19. std::make_unique
unique_ptr<int> p1{ new int(100) };// The same
unique_ptr<int> p2{ make_unique<int>(100)};
void f(unique_ptr<SomeClass> p1,
bool);
bool f2(); // Can throw
// Exception safe
f(make_unique<SomeClass>(), f2());
// Take ownership and can throw
void f(SomeClass* p1);
{
// Not exception safe
f(unique_ptr<SomeClass>(new
SomeClass), f2());
}
unique_ptr<SomeClass> t{ new
SomeClass };
f(t.get());
t.release();
20. std::shared_ptr
std::shared_ptr<SomeClass> p1{new SomeClass };std::shared_ptr<SomeClass> p2 = p1;
std::shared_ptr<int> p{ new int[10] }; // Compiles, but is an error
std::shared_ptr<int> p{ new int[10], std::default_delete<int[]>() };
void thread_func(shared_ptr<vector<int>>& vec) {
...
vec->push_back(5); // Not thread safe
...
}
21. std::shared_ptr
void del(void* data){VirtualFree(data, 0, MEM_RELEASE);
}
void *pData = VirtualAlloc(
nullptr,
0x4000,
MEM_COMMIT,
PAGE_READWRITE);
shared_ptr<void> p(pData, del);
22. Внутреннее устройство shared_ptr
23. Пример использования weak_ptr
class ObjectLoader {map<int, std::weak_ptr<Object>> cache_;
shared_ptr<Object> LoadObject(int id) {
std::shared_ptr<Object> object;
std::weak_ptr<Object> cached = cache_.find(id);
if (cached != cache_.end()) {
object = cached.lock();
if (object != nullptr) return object;
}
object = LoadFromDatabase(id);
cache[id] = object;
}
};
24. Передача smart pointers как аргумента
void f(std::unique_ptr<int> p);// Possible but meaningless
void f(const unique_ptr<Tst>& p);
f(make_unique<int>(10));
// If parameter cannot be null
void f(const Tst& p);
void f(std::unique_ptr<int>& p)
{
p.reset(new int(100));
}
std::unique_ptr<int> p(new int(10));
f(p);
// If parameter can be null
void f(const Tst* p);
25. Передача smart pointers как аргумента
void f(std::shared_ptr<int> arg);{
std::shared_ptr<int> p(new int(10);
f(p);
}
26. Контейнеры
void FillBuffer(void* pBuffer,
size_t bufferSize);
// version with smart pointer
std::unique_ptr<uint8_t[]> buffer{
new uint8_t[1024] };
FillBuffer(buffer.get(), 1024);
// version with raw ponter
uint8_t *buf = new uint8_t[size];
// version with vector
FillBuffer(buf, size);
vector<uint8_t> buffer(size);
delete[] buf;
FillBuffer(&buffer[0], size);
27. Контейнеры
// First DLL// Second DLL
vector<Message> messages;
void FillMessages(vector<Message>&
messages)
FillMessages(messages);
{
for (int i = 0; i < MsgCount(); ++i)
{
messages.push_back(GetMsg(i));
}
}
28. Exception safety
1. Базовая гарантия – контейнер при возникновении исключения остается в согласованномсостоянии; нет утечек ресурсов (пример – вставка диапазона элементов).
2. Строгая гарантия – либо операция заканчивается успешно, либо она не выполняется
вообще (пример vector::push_back).
3. No-throw (nofail) гарантия – операция всегда заканчивается успешно (пример std::swap).
Гарантия предоставляется, если код, предоставляемый пользователем, не оставляет
элементы контейнера в недопустимом состоянии; не приводит к утечкам ресурсов и
деструкторы не кидают исключений.
29. Another guards
1. Часы и таймеры STL.2. Потоки STL (std::thread, std::mutex, std::lock, etc.).
3. Потоки ввода вывода STL (input/output streams).
4. «Стражи» в ATL (CComPtr, CComSafeArray, СComBSTR, CComVariant)
5. «Стражи» в boost (scoped_ptr, scoped_array, share_array)