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

时间:2011-07-16 16:01:58

标签: c++ memory-leaks

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

为了测试,我正在分配1,0000,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');
}

3 个答案:

答案 0 :(得分:2)

确定有几个错误。

没有析构函数。

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

出队并非例外安全:

    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 ++中它通常是气馁的,但被认为是一种风格的东西。就个人而言,我觉得它的用途很混乱。

答案 1 :(得分:2)

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

  

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

当您要求更多内存时,c ++库将重用OS提供的内容。 所以,一般来说,这不是问题。

有时,由于内存碎片,一些内存块确实难以回收。 在这种情况下,您可能想要使用Arena Allocator。

答案 2 :(得分:0)

正如评论中所提到的,您不应该依赖任务管理器来分析程序的内存使用情况。 This question列出了几种适用于内存泄漏检测的Windows工具。