2014-02-21 3 views
3

Мне нужно иметь дело с двумя указателями struct addrinfo. Поскольку я кодирую в C++ (11), я должен сделать код безопасным для кода. Действительно, мои бизнес-структур могут бросить runtime_error. Если вам больше не нужна такая структура, вы должны позвонить freeaddrinfo, чтобы освободить список внутри структуры. Пожалуйста, обратите внимание на следующий код:Умные указатели с addrinfo struct

#include <memory> 
#include <netdb.h> 

class SomeOtherClass 
{ 
    public: 
    SomeOtherClass() : hints(new addrinfo), result(new addrinfo) { /*stuff*/ } 
    ~SomeOtherClass() { freeaddrinfo(result.get()); } // bad things will happen 

private: 
    std::unique_ptr<addrinfo> hints, result; 
}; 

class MyClass : public SomeOtherClass 
{ 
public: 
    MyClass() { /* hints initialization, call to getaddrinfo, etc. */ } 

private: 
    // ... 
}; 

Мои вопросы:

  1. addrinfo является "старой" структуры C, без CTOR/dtor позвонить: безопасно использовать новый?
  2. getaddrinfo требует указатель на указатель на структуру addrinfo: как передать ее с помощью интеллектуальных указателей?
  3. Как насчет звонка freeaddrinfo? Небезопасно удалять (или лучше free) указатель, который удерживает умный указатель.

Для hints проблем нет, так как его срок службы меньше.

+0

Ну, вы действительно не выделяете результирующие структуры информации о адресах самостоятельно, не так ли? Они выделяются функцией 'getaddrinfo'. И вы можете установить пользовательский делектор для интеллектуальных указателей, который может вызывать 'freeaddrinfo'. И подсказки не нужно выделять динамически, даже если вы собираетесь использовать одну и ту же структуру несколько раз. Просто используйте адрес-оператора для нормальной (не указательной) структурной переменной. –

+1

Этот конструктор [небезопасен] (http://herbsutter.com/gotw/_102/) вы должны использовать 'std :: make_unique', если ваш компилятор поддерживает его, или сделать свой собственный эквивалент, если он этого не делает. Вы действительно не хотите иметь дело с утечками памяти от частичной конструкции. Также, если ваш базовый класс будет удерживать ресурсы, ваш деструктор вашего базового класса должен быть 'virtual' – Mgetz

+0

@Mgetz, это всего лишь фрагмент, который поможет вам разобраться в проблеме. Однако я не могу найти место для 'virtual' dtor, потому что базовый класс не является абстрактным. – edmz

ответ

5

Для любого addrinfo вы выделяете себя, безопасно использовать new и delete, так что вы можете использовать реализацию по умолчанию unique_ptr справиться с этим.

Для любых addrinfo, которые выделяет getaddrinfo(), вы должны использовать freeaddrinfo(), чтобы освободить его. Вы все еще можете использовать unique_ptr для этого, но вы должны указать freeaddrinfo() как обычай Deleter, например:

class SomeOtherClass 
{ 
    public: 
    SomeOtherClass() : hints(new addrinfo), result(nullptr, &freeaddrinfo) { /*stuff*/ } 

private: 
    std::unique_ptr<addrinfo> hints; 
    std::unique_ptr<addrinfo, void(__stdcall*)(addrinfo*)> result; 
}; 

Тогда вы можете сделать это:

getaddrinfo(..., &result); 

Или это, если std::unique_ptr не отменяет & оператор:

addrinfo *temp; 
getaddrinfo(..., &temp); 
result.reset(temp); 
+0

Это небезопасно и подвергает риску частичную конструкцию, см. Ссылку в моей комментарий к ОП. – Mgetz

+0

Как насчет второго пункта? – edmz

+0

AFAIK 'make_unique' не позволяет указать пользовательский' Deleter'. –

Смежные вопросы