编写一个测试用例来检查C ++中的内存泄漏

时间:2009-12-16 20:10:48

标签: c++ memory-leaks

注意:这不是家庭作业,而是来自我们的教授为我们的考试提供的实践考试,以帮助我们为我们的考试做好准备

我目前正在攻读编程考试。在他们给我们的一个样本测试中,我们有以下问题:

假设您已经获得了一个模板化容器,该容器包含无序的对象集合。

template <typename T>
class Container {
   public:
      void insert(T *op);
      // EFFECTS: inserts the object pointed to by op into
      // the container
      T *remove();
      // EFFECTS: removes an object from the Container, and
      // returns a pointer to it. Returns NULL if no
      // objects remain in the Container.
      // Note: the implementation can choose which
      // object to return if more than one exists.
      Container(); // ctor
      Container(const Container &l); // copy ctor
      Container &operator=(const Container &l); // assignment
      ~Container(); // dtor
   private:
      ...
};

请注意,这只是界面;为简洁起见,省略了实施细节。 但是,您可以假设实现是基于节点的;链接的节点集合 保持物体。

您怀疑析构函数的实现不满足At-Most-Once不变量的守恒规则,而是泄漏内存。编写验收测试(类似于项目4中的测试)以检查此情况。您必须提供合适的包含类型和执行测试的主体。

请注意,您不能依赖语言未定义的任何行为,您可能不会 假设您可以使用Project 5中的altnew分配器,而您可能没有 覆盖删除操作符。提示:您可以使用全局变量。

我虽然喜欢:

#include <iostream>

using namespace std;

int *p = NULL;

void leak() {
    int *num = new int(5);
    p = num;
    delete num;
}

int main() {
    if ((*p = 6)) {
        cout << "Memory leak\n";
    } else {
        cout << "No Leak\n";
    }
}

这背后的基本思想是我虽然无法写入我没有分配的内存空间。在编译这个测试代码虽然它工作得很好所以显然你可以。关于如何编写这样的测试用例的任何想法?

6 个答案:

答案 0 :(得分:5)

当你说:

void leak() {
    int *num = new int(5);
    p = num;
    delete num;
}

没有内存泄漏。但是,有一个悬空指针(p),如果取消引用,它将导致未定义的行为。

答案 1 :(得分:4)

如果您创建一个类作为模板参数,该类将在其构造函数中为全局变量添加1,并在其析构函数中将该相同的全局变量减少1,该怎么办。

然后你可以在容器上执行你想要的任何测试(创建它,填充它,清空它,删除它等)并通过在容器被销毁之后检查全局变量是否为0来检查内存泄漏。 / p>

答案 2 :(得分:4)

你可以使用像这样的元素类,它计算它的实例:

 class InstCounter {
 public:
   static int counter;
   InstCounter() { counter++; }
   ~InstCounter() { counter--; }
 };
 int InstCounter::counter = 0;

 int main(int argc, char** argv)
 {
   { Container<InstCounter> c;
     // insert elements...
     c.insert(new InstCounter);
   } // calls dtor of c
   if (InstCounter::counter > 0)
     std::cout << "Container is leaking." << std::endl;
   return 0;
 }

答案 3 :(得分:0)

我不确定Project 4和Project 5中列出了什么,但我认为这样做的方法是将一个全局指针(根据提示)分配给您在容器中插入的对象。如果然后销毁容器,它应该销毁其中的对象,并且该全局指针现在应该为null。

答案 4 :(得分:0)

您可以在T构造函数中递增整数全局变量,并在T析构函数中递减它:执行此操作将告诉您容器是否正在销毁T实例。验收测试可以将一些T实例分配到Container实例中,销毁Container,并测试是否破坏了T实例(即是否调用了T析构函数)。

如果没有覆盖删除操作符,我看不到一个简单的方法来判断容器是否不仅破坏了T实例,而且还释放了T实例占用的内存:但是如果它 正在破坏T实例(您可以按照上面第一段中的说明进行测试)然后您可能希望它可能也释放每个实例占用的内存。

答案 5 :(得分:0)

我使用包含引用计数的包含类型。在容器中插入项目时,应增加引用计数。当您销毁容器时,它应该减少回其起始值。引用计数可以保存在全局变量(如建议的)或类中的静态变量中(我通常使用后者,但稍微复杂一点)。