Winapi 第一次接触时自动提交大量分配

Winapi 第一次接触时自动提交大量分配,winapi,unmanaged,Winapi,Unmanaged,如何在Windows中分配内存,但在第一次触摸之前不提交内存 我发现,VirtualAlloc允许我保留一定范围的内存,但我需要在使用之前手动提交该内存的部分。当我第一次引用时,我希望提交是自动的 另外,如果可能的话,我不希望在提交之前将内存归零 (顺便说一句,这可以在Linux上通过设置/dev/zero块的私有内存映射来实现)您可以使用自己设计的智能指针,在第一次解引用时提交它(当然,通过重载解引用和间接操作符) 这是一个示例智能指针,它在第一次取消引用(延迟实例化)时创建给定对象的实例。基

如何在Windows中分配内存,但在第一次触摸之前不提交内存

我发现,
VirtualAlloc
允许我保留一定范围的内存,但我需要在使用之前手动提交该内存的部分。当我第一次引用时,我希望提交是自动的

另外,如果可能的话,我不希望在提交之前将内存归零


(顺便说一句,这可以在Linux上通过设置/dev/zero块的私有内存映射来实现)

您可以使用自己设计的智能指针,在第一次解引用时提交它(当然,通过重载解引用和间接操作符)

这是一个示例智能指针,它在第一次取消引用(延迟实例化)时创建给定对象的实例。基本上是一样的想法:

template <typename T>
struct default_constructor_factory
{
    T * operator ()() { return new T; }
};

template <typename T, typename F = default_constructor_factory<T> >
class lazy_ptr : boost::noncopyable
{
public:
    typedef T element_type;
    typedef T value_type;
    typedef F factory_type;
    typedef lazy_ptr<T,F> this_type;

    lazy_ptr() : m_ptr(), m_factory() { }
    lazy_ptr(F factory) : m_ptr(), m_factory(factory) { }
    ~lazy_ptr() { if (m_ptr != NULL) delete m_ptr; }

    T & operator* () const
    {
        return *get();
    }

    T * operator-> () const
    {
        return get();
    }

    T * get() const
    {
        if (m_ptr == NULL)
            m_ptr = m_factory();
        return m_ptr;
    }

    void reset(T * p)
    {
        if (p != m_ptr)
        {
            if (m_ptr != NULL)
                delete m_ptr;
            m_ptr = p;
        }
    }

    T * release()
    {
        T * p = m_ptr;
        m_ptr = NULL;
        return p;
    }

    // non-dereferencing accessors

    T * peek() const
    {
        // may return NULL
        return m_ptr;
    }

    bool dereferenced() const
    {
        return peek() != NULL;
    }

//  operator bool() const { return dereferenced(); }

    // handle intrinsic conversion to testable bool using unspecified_bool technique
    typedef T * this_type::*unspecified_bool_type;
    operator unspecified_bool_type() const // never throws
    {
        return dereferenced() ? &this_type::m_ptr : NULL;
    }

private:
    // we must remain it's only owner!
    mutable T * m_ptr;

    // our factory generates the needed element on-demand
    mutable factory_type m_factory;
};

// shared_lazy_ptr
//
// we act as a copyable lazy pointer
// essentially, we add reference counting to a single shared lazy pointer
//
template <typename T, typename F = default_constructor_factory<T> >
class shared_lazy_ptr
{
public:
    typedef T element_type;
    typedef T value_type;
    typedef F factory_type;
    typedef lazy_ptr<T,F> ptr_type;
    typedef shared_lazy_ptr<T,F> this_type;

    shared_lazy_ptr() : m_ptr(new ptr_type) { }
    shared_lazy_ptr(F factory) : m_ptr(new ptr_type(factory)) { }

    // copy ctor
    shared_lazy_ptr(const this_type & rhs) : m_ptr(rhs.m_ptr), m_references(rhs.m_references) { }

    // assignment
    this_type & operator = (const this_type & rhs)
    {
        if (m_references.Reattach(rhs.m_references))
            delete m_ptr;
        m_ptr = rhs.m_ptr;
        return *this;
    }

    ~shared_lazy_ptr() 
    {
        if (m_references.IsOnly())
            delete m_ptr;
    }

    T & operator* () const
    {
        return *get();
    }

    T * operator-> () const
    {
        return get();
    }

    T * get() const
    {
        return m_ptr->get();
    }

    void reset(T * p)
    {
        if (p != get())
        {
            if (m_ptr != NULL)
                delete m_ptr;
            m_ptr = p;
        }
    }

    // non-dereferencing accessors

    T * peek() const
    {
        // may return NULL
        return get()->peek();
    }

    bool dereferenced() const
    {
        return peek() != NULL;
    }

//  operator bool() const { return dereferenced(); }

    // handle intrinsic conversion to testable bool using unspecified_bool technique
    typedef T * this_type::*unspecified_bool_type;
    operator unspecified_bool_type() const // never throws
    {
        return dereferenced() ? &this_type::m_ptr : NULL;
    }

private:
    lazy_ptr<T, F> * m_ptr;         // shared *lazy* pointer to the actual object
    ReferenceCount m_references;    // shared reference count to our lazy pointer
};
模板
结构默认值\u构造函数\u工厂
{
T*运算符(){返回新的T;}
};
模板
类lazy\u ptr:boost::noncopyable
{
公众:
类型定义T元素_类型;
类型定义T值_类型;
类型定义F工厂类型;
typedef lazy_ptr此_类型;
lazy_ptr():m_ptr(),m_factory(){}
lazy_ptr(F工厂):m_ptr(),m_工厂(工厂){}
~lazy_ptr(){如果(m_ptr!=NULL)删除m_ptr;}
T&运算符*()常数
{
return*get();
}
T*运算符->()常量
{
返回get();
}
T*get()常量
{
如果(m_ptr==NULL)
m_ptr=m_工厂();
返回m_ptr;
}
无效重置(T*p)
{
如果(p!=m_ptr)
{
如果(m_ptr!=NULL)
删除m_ptr;
m_ptr=p;
}
}
T*释放()
{
T*p=m_ptr;
m_ptr=NULL;
返回p;
}
//非去引用访问器
T*peek()常数
{
//可能返回NULL
返回m_ptr;
}
布尔解引用()常量
{
return peek()!=NULL;
}
//运算符bool()常量{return dereferenced();}
//使用未指定的布尔技术处理到可测试布尔的内部转换
typedef T*此类型::*未指定的类型;
运算符未指定\u bool\u type()常量//从不抛出
{
返回取消引用的()?&此类型::m_ptr:NULL;
}
私人:
//我们必须保持它的唯一主人!
可变T*m_ptr;
//我们工厂按需生产所需的元件
可变工厂型m工厂;
};
//共享\u懒惰\u ptr
//
//我们充当可复制的惰性指针
//本质上,我们将引用计数添加到单个共享惰性指针
//
模板
类共享\u lazy\u ptr
{
公众:
类型定义T元素_类型;
类型定义T值_类型;
类型定义F工厂类型;
typedef lazy_ptr ptr_type;
typedef共享\u懒惰\u ptr此\u类型;
共享_lazy_ptr():m_ptr(新的ptr_类型){}
共享的ptr(F工厂):m_ptr(新的ptr_类型(工厂)){}
//复印机
共享_-lazy_-ptr(const this_-type&rhs):m_-ptr(rhs.m_-ptr),m_-references(rhs.m_-references){}
//分配
此类型和运算符=(常量此类型和rhs)
{
if(m_参考。重新连接(rhs.m_参考))
删除m_ptr;
m_ptr=rhs.m_ptr;
归还*这个;
}
~shared_lazy_ptr()
{
if(m_references.IsOnly())
删除m_ptr;
}
T&运算符*()常数
{
return*get();
}
T*运算符->()常量
{
返回get();
}
T*get()常量
{
返回m_ptr->get();
}
无效重置(T*p)
{
if(p!=get())
{
如果(m_ptr!=NULL)
删除m_ptr;
m_ptr=p;
}
}
//非去引用访问器
T*peek()常数
{
//可能返回NULL
返回get()->peek();
}
布尔解引用()常量
{
return peek()!=NULL;
}
//运算符bool()常量{return dereferenced();}
//使用未指定的布尔技术处理到可测试布尔的内部转换
typedef T*此类型::*未指定的类型;
运算符未指定\u bool\u type()常量//从不抛出
{
返回取消引用的()?&此类型::m_ptr:NULL;
}
私人:
lazy_ptr*m_ptr;//指向实际对象的共享*lazy*指针
ReferenceCount m_references;//对我们的惰性指针的共享引用计数
};

大概目标是延迟分配地址备份,而不是在首次使用时明确承诺?如果是这样,Windows似乎会自动为您执行此操作

相关报价:

作为动态的替代方案 分配,该过程可以简单地 提交整个区域,而不是 只保留它。这两种方法都有效果 在相同的物理内存使用情况下 因为提交的页面不会使用 任何物理存储,直到 第一次访问


至于新页面被重置为零,我相信这是一个安全特性,无法避免。(系统有一个特殊的线程,当出现死区时,它会将页面归零,因此如果运气好的话,总会有一个归零的页面在必要时可以立即使用。)

这里的问题是,它只允许我为有足够可用虚拟内存的页面进行分配。我想进行巨大的分配(数量级大于RAM+交换)。很明显,如果我接触太多的页面,这将在将来的某个时候失败,但我不介意。我认为,文档建议VirtualAlloc将完全按照您的意愿来做?页面文件将根据需要增长,磁盘空间允许,因此没有硬限制。至于空闲虚拟内存,不管你做什么,你都会受到它的限制,因为这是地址空间的限制。(您可以使用PAE在32位模式下再添加一些位-Windows支持这一点,但我从未使用过。)我不想受磁盘空间的限制(即ram+交换)。。我想在64位上进行真正巨大的分配,并且只分配hav