技艺实践

资源安全

2018-06-28  本文已影响120人  刘光聪

提出问题

在所有异常分之里记得释放资源,存在较为严重的安全隐患。此处,引入ScopedExit的封装,使用C++特有的RAII机制,在析构函数中完成资源的安全释放;即使程序在运行中抛出异常,也能保证资源的安全释放。

函数指针

int fd = open("file.dat", O_RDONLY);
ScopedExit e(fd, close);

Lambda表达式

File* f = fopen("file.dat", "r");
ScopedExit e(f, [](FILE* f) {
  fclose(f);
});

ScopedExit实现

此处,显式地加上+deleter,使得lambda表达式能够安全地转型为原生的函数指针类型。举个例子,auto test = +[]{}test的类型推演为void(*)()

class ScopedExit {
  using Handle  = void*;
  using Deleter = void(*)();
  using Wrapper = void(*)(Deleter*, Handle*);

  Wrapper wrapper;
  Deleter deleter;
  Handle handle;

public:
  template<typename T, typename D>
  ScopedExit(T handle, D deleter)
      : deleter(reinterpret_cast<Deleter>(+deleter))
      , handle(reinterpret_cast<Handle>(handle)) {
    wrapper = [](Deleter* deleter, Handle* handle) {
      auto d = (*reinterpret_cast<D*>(deleter));
      auto h = (*reinterpret_cast<T*>(handle));
      d(h);
    };
  }

  ~ScopedExit() {
    wrapper(&deleter, &handle);
  }
};
上一篇下一篇

猜你喜欢

热点阅读