我的软件在大量分配后仍然使用一些内存

My software is still using some memory after lots of allocations

本文关键字:内存 软件 分配 我的      更新时间:2023-10-16

我在Windows上用c++写了一个小的队列类。

只是为了测试,我分配了1,000,000个int并读取它们。

队列正在正确地完成它的工作,并且非常快,但问题是在完成释放后,任务管理器报告了一些内存使用情况。例如,我仍然得到2MB的内存,尽管所有这些整数导致400MB以上的内存。

我认为这是由于操作系统没有执行某种GC或其他原因,但是现在我发现当我分配100,000,000个整数(之前的数字的10倍)时,这个值(2MB)变成了13MB。我找不到漏洞。

下面是代码;如您所见,我释放了所有内容:

#pragma once
#include <exception>
template <class T>
class colist_item
{
public:
    colist_item() { }
    ~colist_item() { }
    T value;
    colist_item *next;
};
template <class T>
class colist
{
public:
    colist() { this->m_root = NULL; this->m_count = 0; }
    ~colist() { }
    void enqueue(T value);
    T dequeue();
    T *peek();
    int count();
private:
    colist_item<T> *m_root;
    int m_count;
};
template <class T>
void colist<T>::enqueue(T value)
{
    if (this->m_root == NULL) {
        this->m_root = new colist_item<T>();
        this->m_root->value = value;
        this->m_root->next = NULL;
    } else {
        colist_item<T> *tempitem = new colist_item<T>();
        tempitem->value = value;
        tempitem->next = this->m_root;
        this->m_root = tempitem;
    }
    this->m_count++;
}
template <class T>
T colist<T>::dequeue()
{
    if (this->m_root == NULL) {
        throw std::exception();
    } else {
        T retval = this->m_root->value;
        colist_item<T> *next = this->m_root->next;
        delete this->m_root;
        this->m_root = next;
        this->m_count--;
        return retval;
    }
}
template <class T>
T *colist<T>::peek()
{
    if (this->m_root == NULL) {
        return NULL;
    } else {
        T retval = this->m_root->value;
        return &retval;
    }
}
template <class T>
int colist<T>::count()
{
    return this->m_count;
}
主:

#include <iostream>
#include <limits>
#include "colist.h"
#include <time.h>
const int kNumItems = 100000000;
using namespace std;
void puttest(colist<int> *list)
{
    for(int i = 0; i < kNumItems; i++)
        list->enqueue(i);
}
void readtest(colist<int> *list)
{
    for(int i = 0; i < kNumItems; i++)
        list->dequeue();
}
int main(int argc, char *argv[])
{
    colist<int> list;
    cout << "Testing with : " << kNumItems << " elements" << endl;
    clock_t start = clock();
    puttest(&list);
    clock_t end = clock();
    double ms = ((end - start));
    cout << "puttest: " << ms << endl;
    start = clock();
    readtest(&list);
    end = clock();
    ms = ((end - start));
    cout << "readtest: " << ms << endl;
    cin.ignore(std::numeric_limits<std::streamsize>::max(), 'n');
}

有几个bug

没有析构函数。

您没有泄漏任何内存,因为您删除了所有项。但是,如果您没有手动删除它们,那么您的类在超出作用域时就会泄漏。添加一个析构函数,只删除列表中的所有项。

Dequeue不是异常安全:

    T retval = this->m_root->value;
    colist_item<T> *next = this->m_root->next;
    delete this->m_root;   // If T is badly designed it could potentially throw an exception.
    this->m_root = next;   // Now you have m_root pointing at a bad object. The idea is to
                           // make sure an exception can not damage your internal structure
                           // of your object. Thus remove it from the chain before you call
                           // delete.
   // Like this
   T               retval    = m_root.value;
   colist_item<T>* oldhead   = m_root;
   m_root                    = oldhead->next;
   // Internal structure updated.
   // Safe to do dangerous tasks.
   delete oldhead;

在构造

时使用初始化列表
colist() { this->m_root = NULL; this->m_count = 0; }
// should be
colist():  m_root(NULL), m_count(0) {}

你不需要到处使用this

我知道它在java中是被鼓励的,但在c++中通常不被鼓励,但被认为是一种风格。

运行http://valgrind.org/以确保没有内存泄漏。

我如何告诉操作系统我已经完成了分配,它可以释放未使用的内存?

当你请求更多内存时,c++库将重用操作系统提供的内存。所以,一般来说,这不是问题。

有时候,由于内存碎片,一些内存块真的很难回收。在这种情况下,您可能需要使用Arena分配器。

正如在注释中提到的,您不应该依赖任务管理器来分析程序的内存使用情况。这个问题列出了几个适合于内存泄漏检测的Windows工具。