注意:这不是家庭作业,而是来自我们的教授为我们的考试提供的实践考试,以帮助我们为我们的考试做好准备
我目前正在攻读编程考试。在他们给我们的一个样本测试中,我们有以下问题:
假设您已经获得了一个模板化容器,该容器包含无序的对象集合。
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";
}
}
这背后的基本思想是我虽然无法写入我没有分配的内存空间。在编译这个测试代码虽然它工作得很好所以显然你可以。关于如何编写这样的测试用例的任何想法?
答案 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)
我使用包含引用计数的包含类型。在容器中插入项目时,应增加引用计数。当您销毁容器时,它应该减少回其起始值。引用计数可以保存在全局变量(如建议的)或类中的静态变量中(我通常使用后者,但稍微复杂一点)。