内存使用STL数据结构,windows与linux

swe*_*egi 11 c++ memory-management stl

我有一个大量使用的程序std::map.在Windows下,Linux下使用的内存要多得多.有谁知道为什么会这样?

Linux的: Last process took 42.31 s and used not more than 909 MB (RSS 900 MB) of memory

视窗: Last process took 75.373 s and used not more than 1394 MB (RSS 1395 MB) of memory

我在命令行上使用gcc 4.4.3和VS 2010 C++编译器,具有发布设置.

编辑:很抱歉回答最近的问题......

代码如下所示:

enum Symbol {
    ...
}

class GraphEntry {

    public:

    ...

    virtual void setAttribute (Symbol name, Value * value) = 0;

    const Value * attribute (Symbol name) const;

    private:

    std::map<Symbol, Attribute> m_attributes;
};

class Attribute {

    public:

    Attribute (Symbol name, Value * val);

    ...

    Symbol name () const;

    Value * valuePointer () const;

    void setValuePointer (Value * p);

    private:

    Symbol m_name;

    Value * m_value;
};

class Graph : public GraphEntry {

    ...

    public:

    Node * newNode (...);

    Graph * newSubGraph (...);

    Edge * newEdge (...);

    ...

    setSomeAttribute (int x);

    setSomeOtherAttribute (float f);

    ...

    private:

    std::vector<GraphEntry *> m_entries;
};
Run Code Online (Sandbox Code Playgroud)

整个过程描述了一个图形结构,它可以在其节点和边缘上保存一些属性.Value它只是一个基类,派生类可以包含任意类型的值,如intstd::string.

编辑2:在Windows下,我使用以下标志: -DRELEASE -DNDEBUG -DQT_NO_DEBUG -DQT_NO_DEBUG_OUTPUT -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -DNOMINMAX /O2 /MD /Gy /EHsc

编辑3:从linux下的/ proc文件中读取内存使用情况(如memuse).在Windows下,调用了一些WinAPI函数,但我不是这方面的专家,所以这就是我所能说的.

编辑4:使用/GS--D_SECURE_SCL结果Last process took 170.281 s and used not more than 1391 MB (RSS 1393 MB) of memory

Mat*_*ner 8

你会发现Windows上的内存使用量大约是1到2倍.除了堆算法,Windows malloc(),以及随后在堆上分配的任何数据结构new(例如std::map具有默认分配器类型的节点)都与16个字节对齐.在Linux上,glibc默认为8字节对齐.假设由于碎片,优化收获未使用的页面等而导致差异平滑,您可以预期差异将变得不那么明显

快速检查代码表明映射键和值类型应分别为4和8字节(SymbolAttribute).这些将在Linux上最多8个字节,在Windows上最多16个字节.您应该有相同数量的映射节点,至少在MSVC实现中,这些映射看起来至少消耗22个字节,由于其成员对齐规则,MSVC将扩展为32,这也是它的malloc粒度.GCC将其扩展到24,意味着MSVC到GCC/Linux的每个节点大约有48个字节.Windows上的内存使用量大约增加50%.

这是MSVC中使用的节点结构,如果您感兴趣,我可以查看GCC等效项:

struct _Node
    {   // tree node
    _Nodeptr _Left; // left subtree, or smallest element if head
    _Nodeptr _Parent;   // parent, or root of tree if head
    _Nodeptr _Right;    // right subtree, or largest element if head
    value_type _Myval;  // the stored value, unused if head
    char _Color;    // _Red or _Black, _Black if head
    char _Isnil;    // true only if head (also nil) node
Run Code Online (Sandbox Code Playgroud)

我会为那些不熟悉内存使用情况的人添加内容,有几个因素在起作用:

  • 内存以块为单位进行分配,舍入到所使用的分配机制的下一个对齐倍数.对于堆,malloc()正在使用对齐规则(除非您破坏通常的堆或使用除默认值之外的其他分配器).
  • 虚拟存储器由系统"提供",称为页面,帧大小的整数倍,这超出了本问题的范围.这对答案影响很小,因为与所讨论的页面大小(4K)相比,内存使用量非常大,而且与使用中的对齐(8和16)相比,页面大小相当大.


Mat*_* M. 7

每个编译器都附带自己的STL实现,因此您要进行比较:

  • GCC STL + Linux分配例程
  • VC++ STL + Windows分配例程

在这里绘制有意义的比较是相当困难的,因为您不知道哪个分配例程或STL实现(或可能两者)实际上负责.

我确实假设你没有将32位程序与64位程序进行比较,因为这样做的意义就更小了.


vob*_*ect 6

某些版本的VC++也在发布版本中使用了已检查的迭代器(_SECURE_SCL).VC2005VC2008默认打开它们.VC2010 默认禁用它们

根据您的编译器,这可能是检查(和关闭)的另一件事.