返回题库

文件描述符 RAII

File Descriptor Raii

专题
Systems & Architecture / 系统与架构
难度
L1
来源
MyntBit

题目详情

RAII(资源获取即初始化)是 C++ 系统编程的基础惯用法,确保确定性资源管理。通过将 POSIX 文件描述符等资源的生命周期绑定到对象生命周期,防止资源泄漏。

任务:实现文件描述符 RAII 类,在构造时获取文件描述符,在析构时释放。支持移动语义但禁止复制。提供获取原始描述符的方法。

英文原题

Resource Acquisition Is Initialization (RAII) is a fundamental idiom in C++ systems programming, ensuring deterministic resource management essential for high-frequency trading environments where latency and stability are paramount. By binding the life cycle of a resource, such as a POSIX file descriptor, to the lifetime of an object, developers prevent resource leaks and ensure proper cleanup. This pattern is critical for maintaining robust infrastructure in quantitative finance applications.

解析

问题分析

RAII(资源获取即初始化)确保文件描述符在离开作用域时自动关闭,避免资源泄漏。在交易系统中管理 socket 连接、日志文件和共享内存句柄时尤其重要。

实现

class FileDescriptor {
    int fd_;
public:
    explicit FileDescriptor(int fd) : fd_(fd) { if (fd_ < 0) throw std::runtime_error("Bad fd"); }
    ~FileDescriptor() { if (fd_ >= 0) ::close(fd_); }
    FileDescriptor(const FileDescriptor&) = delete;
    FileDescriptor& operator=(const FileDescriptor&) = delete;
    FileDescriptor(FileDescriptor&& o) noexcept : fd_(o.fd_) { o.fd_ = -1; }
    int get() const { return fd_; }
};

// 使用
{
    FileDescriptor sock(::socket(AF_INET, SOCK_STREAM, 0));
    // ... 使用 sock.get() ...
} // sock 自动关闭

复杂度与边界

  • 时间复杂度:构造/析构 O(1)
  • 空间复杂度:O(1)
  • 边界条件:(1) 移动后源对象的 fd_ 设为 -1 防止双重关闭 (2) 不支持拷贝——每个 fd 唯一拥有 (3) -1 代表无效 fd

英文解析

Analysis

RAII (Resource Acquisition Is Initialization) ensures file descriptors are automatically closed when leaving scope, preventing resource leaks. This is especially important in trading systems for managing socket connections, log files, and shared memory handles.

Solution

class FileDescriptor {
    int fd_;
public:
    explicit FileDescriptor(int fd) : fd_(fd) { if (fd_ < 0) throw std::runtime_error("Bad fd"); }
    ~FileDescriptor() { if (fd_ >= 0) ::close(fd_); }
    FileDescriptor(const FileDescriptor&) = delete;
    FileDescriptor& operator=(const FileDescriptor&) = delete;
    FileDescriptor(FileDescriptor&& o) noexcept : fd_(o.fd_) { o.fd_ = -1; }
    int get() const { return fd_; }
};

// Usage
{
    FileDescriptor sock(::socket(AF_INET, SOCK_STREAM, 0));
    // ... use sock.get() ...
} // sock auto-closed

Complexity & Edge Cases

  • Time complexity: construct/destruct O(1)
  • Space complexity: O(1)
  • Edge cases: (1) After move, source fd_ set to -1 prevents double-close (2) Copy disabled - each fd uniquely owned (3) -1 represents invalid fd

Verification

Create and destroy FileDescriptor objects, verify close() is called exactly once per fd. Test move semantics confirm no double-close. Verify exception on invalid fd.

Key Considerations

RAII-based fd management eliminates an entire class of resource leak bugs. In long-running trading processes, leaked file descriptors (sockets, shm handles) accumulate over days and eventually exhaust the fd limit, causing connection failures. RAII guarantees cleanup even when exceptions propagate.