none
VC++ 6.0中CArray中保存大量对象时内存无法释放的问题,请各位指点 RRS feed

  • 问题

  • 复现条件:

    1、编译环境:VC++ 6.0

    2、以release方式编译,全部使用默认的编译选项和参数,并且不使用调试器执行该应用程序

    3、在数组中存放超过100万个对象

    执行程序后,在我的电脑上,接近有85M的内存无法自动释放。

    有哪位能够帮忙解释并解决这个问题吗?

    btw:受限于历史项目代码,我的应用程序开发环境无法迁移到更新的VisualStudio开发环境,因此不要建议我升级。谢谢。

    #include "afxtempl.h"

    long int g_cCount = 0; // 记录构造函数调用次数
    long int g_dCount = 0; // 记录析构函数调用次数

    class CMyTest
    {
    public:
    CString m_str;


    CMyTest()
    {
    m_str = "test string";

    g_cCount++;
    }


    ~CMyTest()
    {
    g_dCount++;
    }

    };

    typedef CArray<CMyTest,CMyTest&> CArrayTest;



    void Test()
    {
    g_cCount = 0;
    g_dCount = 0;

    CArrayTest testArray;

    int count = 1000000; // 一百万个对象
    for(int i =0;i < count; i++ )
    {
    CMyTest testObj;
    testObj.m_str = "test string";

    testArray.Add(testObj);
    }

    testArray.RemoveAll();
    testArray.FreeExtra();
    }

    void CTestMemDlg::OnOK() 
    {
    Test();

    CString strInfo;
    strInfo.Format("Object construction: %d  destruction: %d \r\n",g_cCount,g_dCount);
    AfxMessageBox("finish\r\n"+strInfo);
    }

    2016年6月5日 14:02

全部回复

  • Hi zhouxiaohui

    感谢在MSDN论坛发帖。

     

    根据CArray Class的官方文档中的介绍, 使用数组之前,使用setSize来设置它的大小和分配内存。如果你不使用的setSize,将元素添加到数组将导致它重新分配内存并复制。频繁的重新分配内存和复制是低效的,而且容易产生内存碎片。因此,请在使用数组前,使用setSize给数组分配内存。

     

    Best Regards,

    Sera Yu


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.


    • 已编辑 Baron Bi 2016年6月6日 5:52
    2016年6月6日 5:51
  • 按照你的说法,我也尝试了先用SetSize来设置数据的总大小,并用SetAt(而不用Add)来添加对象到数组中。

    但是,没有任何效果。

    2016年6月6日 13:17
  • 我继续做了各种实验,发现问题并不是仅仅在CArray上出现。

    在下面的例子中,我仅仅只是创建了若干个CString对象,然后再逐一将其删除。程序执行完之后,同样大概有86M的内存无法释放。

    我彻底懵了。这到底是怎么回事呢?

    一百万个对象并不是必须的,只不过是占用内存比较明显而已。一千或者一万个对象都会存在同样的内存无法完全释放的问题。

    void TestXXX()
    {
    int count = 1000000;

    CString** pStrArray = new CString*[count];

    for( int i =0; i< count; i++)
    {
    CString* pStr = new CString();
    pStr->Format("some string %d",i);

    pStrArray[i] = pStr;
    }


    for( int j =0; j< count; j++)
    {
    CString* pStr = pStrArray[j];

    delete pStr;
    }

    delete []pStrArray;

    }

    2016年6月6日 13:21
  • 为了避免频繁的分配释放操作导致的内存碎片的问题,您能否只分配一次,即程序启动的初始阶段分配一次大内存,程序结束之前统一释放呢?

    Visual C++ enthusiast, like network programming and driver development. At present is being engaged in the WinCE/Windows Mobile platform embedded development.

    2016年6月8日 5:34
    版主
  • 使用我上面的示例代码,只需要运行一次,就会明显看到内存的增大,运行完之后内存不会立即释放。

    我尝试将CArray、CString都使用std::vector和std::string 替代之后,运行程序之后内存会立即释放。

    现在,我严重怀疑VC++ 6.0中CString类的内存管理机制有一定的问题。

    2016年6月11日 13:43