【问题标题】:smart pointer to manage socket file descriptor管理套接字文件描述符的智能指针
【发布时间】:2015-04-13 20:46:16
【问题描述】:

如果指针超出范围,智能指针会清除内存。我想把它适应一个文件描述符,比如一个套接字。你需要一个用户定义的删除器,因为 close() 是释放文件描述符 (fd) 资源的函数。

我发现this 有用的页面,不幸的是,大多数方法对我不起作用。下面是我到目前为止找到的一个可行的解决方案,这有点讨厌。因为 uniqu_ptr 需要一个我创建的指针 int *fd 来存储 fd 值,因此,我必须在我的自定义删除器中关闭 (*fd) 并删除 fd。

(1)有没有更好的办法?

基于上述网页提供的提示的选项 A 和 B 更好,但会导致奇怪的编译器错误。

(2)有谁知道如何正确使用这些替代品?

我正在使用带有 CONFIG += c++11 选项和 gcc 版本 4.8.2 的 Qt Creator 3.0.1

#include "ccommhandler.h"

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <memory>

#include <qdebug.h>

//for Option A and B
struct CloseHandleDeleter {
    typedef int pointer;
    void operator()(int handle) const
    {
    }
};

//custom deleter, working
class MyComplexDeleter
{

public:
    MyComplexDeleter() {}

    void operator()(int* ptr) const
    {
        qDebug() << "Deleting ";
        close(*ptr);
        delete ptr;
    }
};

CCommHandler::CCommHandler()
{
    //Option A doesn't work
    //std::unique_ptr<int, CloseHandleDeleter> file( socket(AF_INET, SOCK_STREAM, 0) );
    //Option B doesn't work
    //std::unique_ptr<int, int()(int)> filePtr(  socket(AF_INET, SOCK_STREAM, 0) , close);

    MyComplexDeleter deleter;
    int *fd = new int;
    *fd = socket(AF_INET, SOCK_STREAM, 0);
    std::unique_ptr<int, MyComplexDeleter> p( fd , deleter);

}

编辑:

Nevin 发布的答案是正确的,它解决了我最初的问题。

learnvst 的评论让我重新思考了我的问题,我不得不说我可能让它比需要的复杂得多,因为下面的简单类也应该解决我的自动释放资源内存的问题,或者如我的情况,关闭文件描述符:

class SocketHandler
{
   int _fd;
 public:
   SocketHandler(int FD):_fd(FD){}
   ~SocketHandler() { if(_fd!=-1) close(_fd); }

   operator int() const { return _fd; }
};

【问题讨论】:

  • 为什么不把套接字的东西包装到一个类中并关闭 dtor 中的套接字呢?然后你不需要使用删除器,因为当智能指针释放资源时,一切都会很好地结束。
  • 一个unique_ptr 必须持有一个指针socket() 在非 Windows 平台上不返回 指针。这就是为什么选项 A 和 B 不起作用,但选项 C 起作用的原因。

标签: sockets c++11 smart-pointers


【解决方案1】:

因为 fd 不是指针,所以我不会尝试将其归类为 unique_ptr。相反,创建一个其接口基于unique_ptr 的自定义类,如(注意:完全未经测试):

class unique_fd
{
public:
    constexpr unique_fd() noexcept = default;
    explicit unique_fd(int fd) noexcept : fd_(fd) {}
    unique_fd(unique_fd&& u) noexcept : fd_(u.fd_) { u.fd_ = -1; }

    ~unique_fd() { if (-1 != fd_) ::close(fd_); }

    unique_fd& operator=(unique_fd&& u) noexcept { reset(u.release()); return *this; }

    int get() const noexcept { return fd_; }
    operator int() const noexcept { return fd_; }

    int release() noexcept { int fd = fd_; fd_ = -1; return fd; }
    void reset(int fd = -1) noexcept { unique_fd(fd).swap(*this); }
    void swap(unique_fd& u) noexcept { std::swap(fd_, u.fd_); }

    unique_fd(const unique_fd&) = delete;
    unique_fd& operator=(const unique_fd&) = delete;

    // in the global namespace to override ::close(int)
    friend int close(unique_fd& u) noexcept { int closed = ::close(u.fd_); u.fd_ = -1; return closed; }

private:
    int fd_ = -1;
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-08
    • 2014-04-25
    • 2012-11-02
    • 1970-01-01
    • 2012-11-12
    • 2011-03-31
    • 1970-01-01
    相关资源
    最近更新 更多