首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >内部安全文件系统

内部安全文件系统
EN

Code Review用户
提问于 2020-07-10 22:09:45
回答 1查看 91关注 0票数 1

win_xept.hpp -一个基本的windows异常

代码语言:javascript
复制
#include "../utl_macro.hpp"

namespace xept
{
    using win_t = struct utl_exception // utl_exception randomly generates a name
                                       // this hides exception names from rtti
    {
        DWORD e = GetLastError( );
    };
}

ramfile.hpp -在ram中需要数据的任何类型文件的接口。

代码语言:javascript
复制
#pragma once

class ramfile_t
{
public:
    virtual std::uintmax_t size( ) = 0;
    virtual std::vector< std::byte > raw( ) = 0;
    virtual void overwrite( std::vector< std::byte > const & raw,
                            std::size_t const & off = 0 ) = 0;
    virtual void set( std::vector< std::byte > const & raw ) = 0;
};

ramfile_xept.hpp -基本的ramfile异常

代码语言:javascript
复制
#include "../win_xept.hpp"

namespace xept
{
    using ramfile_t = struct utl_exception:
        win_t
    { };
}

ramfile_disk.hpp -磁盘的基本文件

代码语言:javascript
复制
class ramfile_disk_t:
    public ramfile_t
{
public:
    ramfile_disk_t( std::filesystem::path path ):
        path( std::move( path ) ),
        file_guard( file_locks[ this->path.c_str( ) ] )
    {
        assert( path.is_absolute( ) );
    }

    std::uintmax_t size( ) final
    {
        return std::filesystem::file_size( path );
    }

    std::vector< std::byte > raw( ) final
    {
        std::basic_ifstream< std::byte > file( path,
                                               std::ofstream::binary );

        assert( file.is_open( )
                && file.good( ) );

        file.seekg( 0 );

        return std::vector< std::byte >( std::istreambuf_iterator< std::byte >( file ),
                                         std::istreambuf_iterator< std::byte >( ) );
    }

    void set( std::vector< std::byte > const & data ) final
    {
        std::basic_ofstream< std::byte > file( path,
                                               std::ofstream::binary | std::ofstream::trunc );

        assert( file.is_open( )
                && file.good( ) );

        file.write( data.data( ),
                    data.size( ) );
    }

    void overwrite( std::vector< std::byte > const & data,
                    std::size_t const & off = 0 ) final
    {
        std::basic_ofstream< std::byte > file( path,
                                               std::ofstream::binary );

        assert( file.is_open( )
                && file.good( ) );

        file.seekp( off ).write( data.data( ),
                                 data.size( ) );
    }

    void set_attr( bool readonly,
                   bool hidden )
    {
        DWORD attr = 0;

        if ( readonly )
            attr |= FILE_ATTRIBUTE_READONLY;
        if ( hidden )
            attr |= FILE_ATTRIBUTE_HIDDEN;

        if ( 0 == SetFileAttributes( path.c_str( ),
                                     attr
                                         ? attr
                                         : FILE_ATTRIBUTE_NORMAL ) )
            throw xept::ramfile_disk_attr_t( );
    }

protected:
    std::filesystem::path path;

private:
    using file_locks_t = std::unordered_map< std::wstring_view,
                                             std::mutex >;
    static file_locks_t file_locks;

    std::lock_guard< file_locks_t::mapped_type > file_guard;
};

ramfile_disk_xept.hpp -可从ramfile_disk抛出的异常

代码语言:javascript
复制
#include "ramfile_xept.h"

namespace xept
{
    using ramfile_disk_attr_t = struct utl_exception:
        ramfile_t
    { };
}
EN

回答 1

Code Review用户

回答已采纳

发布于 2020-07-11 09:05:05

设计:设计非常糟糕。多想想你打算如何使用它。目前,它容易出现死锁。

例如,在同一文件的代码中的两个不同位置创建两个ramfile_disk_t实例。第二个实例将被阻塞,直到第一个实例完成。这就是你想要的吗?这是您希望使用代码的唯一方式吗?

至少添加如下选项:

  1. “共享使用”--如果您只想阅读,就没有理由禁用来自多个地方的访问。此外,用户可能希望自己管理读写安全,而不是依赖粗糙的方法。
  2. “尝试打开”--如果锁定,返回false。
  3. “打开”-如果锁了就扔。
  4. “等待打开”--如果锁定,等待直到解锁。
  5. “锁定使用”--在读/写时锁定/解锁互斥锁,而不是创建/销毁类。

Technical问题

  1. 避免#include "../win_xept.hpp"。假设某个地方有另一个win_xept.hpp文件,用户添加了一个包含路径,这会导致加载错误的win_xept.hpp。这导致了腐败。如果有什么需要的话,您最好为所有的代码文件创建一个额外的文件夹,这样才更安全。所以你总是包括#include "my_codebase/current_project/win_xept.hpp"。作为奖励,您的代码将得到更好的组织。
  2. 通常,可以为抽象类创建一个静态create函数,根据用户的请求实例化实现。这样,用户在任何时候都不需要包含实现的头。
  3. ramfile_t是一个具有虚拟函数的类。因此,它应该有一个虚拟析构函数(virtual ~ramfile_t() = default)。对于纯抽象类尤其如此。另外,你真的认为你会有更多的这个类的实现,为什么还要考虑这个接口呢?
  4. ramfile_disk_t与静态成员file_locks存在数据竞争问题。每次访问它时,都应该使用互斥锁来保护它。
  5. 我不是100%确定,但是很可能是std::vector< std::std::istreambuf_iterator< >( std::istreambuf_iterator< std::std::istreambuf_iterator< >( file ),std::istreambuf_iterator( ) );是一个非常慢的读取文件的方法。考虑使用更低级别的函数,比如freadiostreamread,而不是基于迭代器的方法。至少做些测试。
  6. 这有点挑剔,但是在overwrite方法中是否有任何理由将D36作为const引用传递?只需通过值std::size_t off传递它;不仅通过引用传递速度更慢,而且当您试图在异步线程中调度函数时,它就会变得很麻烦。
票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/245298

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档