Overriding new and delete operator
-
Hi!
I'm working on QT and I'm currently writing test application to our code. We decided to try to detect also memory leaks with our objects, so we have overridden new and delete operators in following way.
@
// main.cppvoid * operator new(unsigned int size) throw (std::bad_alloc)
{
void *ptr = (void *)malloc(size);
Pointers::instance()->append(ptr);
return(ptr);
};void operator delete(void *p) throw()
{
Pointers::instance()->removeAll(p);
free(p);
};
@class Pointers is singleton class, containing list of all allocated pointers. Because memory leaks are easy to detect from test cases, we keep only track about number of pointers.
The Problem is:
@
// test.cppvoid TestClass::testCanary() {
QVERIFY(true);// Makes sure that environment works for new and delete -operators. QCOMPARE(NUM_POINTERS(), 0); int *i = new int(2); QCOMPARE(NUM_POINTERS(), 1); delete i; QCOMPARE(NUM_POINTERS(), 0); QWidget *w = new QWidget(); QCOMPARE(NUM_POINTERS(), 1); delete w; QCOMPARE(NUM_POINTERS(), 0); // <------ FAILS!!!???
}
@The marked line fails and this happens only, when compiling code with Mingw32-make (GNU Make 3.81) coming with QT 4.7 packet. On Visual Studio 2008, the test passes.
[edit] please use @ for code
-
Some more information...
This does not work:
@
// test.cppvoid TestClass::testCanary() {
QVERIFY(true);// Makes sure that environment works for new and delete -operators. QCOMPARE(NUM_POINTERS(), 0); int *i = new int(2); QCOMPARE(NUM_POINTERS(), 1); delete i; QCOMPARE(NUM_POINTERS(), 0); QWidget *w = new QWidget(); QCOMPARE(NUM_POINTERS(), 1); delete w; QCOMPARE(NUM_POINTERS(), 0); // <------ FAILS!!!???
}
@But this works:
@
// test.cppvoid TestClass::testCanary() {
QVERIFY(true);// Makes sure that environment works for new and delete -operators. QCOMPARE(NUM_POINTERS(), 0); int *i = new int(2); QCOMPARE(NUM_POINTERS(), 1); delete i; QCOMPARE(NUM_POINTERS(), 0); QWidget *w = new QWidget(); QCOMPARE(NUM_POINTERS(), 1); ::delete w; // <------ notice :: QCOMPARE(NUM_POINTERS(), 0); // <------ SUCCEEDS!!!
}
@Anyone can explain? Of course, it is not solution to add '::' everywhere in the code.
-
Hmmno.
I used the following code:
@
#include <QApplication>
#include <QWidget>
#include <QDebug>int ptrs = 0;
void * operator new(size_t size) throw (std::bad_alloc)
{
void *ptr = (void *)malloc(size);
ptrs++;
return(ptr);
};void operator delete(void *p) throw()
{
ptrs--;
free(p);
};int main(int argc, char *argv[])
{
QApplication app(argc, argv);
qDebug() << ptrs;
QWidget *w = new QWidget;
qDebug() << ptrs;
delete w;
qDebug() << ptrs;
}
@Which resulted in the following output:
@1101
1107
1104@That probably means that you cannot assume that the amount you expect is almost always wrong...
Anyway, in which objects do you expect memory leaks?
-
Full source here
unittest_operatortest.pro
@
CONFIG += qtestlib consoleDEFINES += BUILD_QTILIB
SOURCES += main.cpp
SOURCES += unittest_operatortest.cppHEADERS += unittest_operatortest.h
@unittest_operatortest.h
@
#ifndef UNITTEST_OPERATORTEST
#define UNITTEST_OPERATORTEST#include <QObject>
#include <new>/*********************************************************************
- DECLARATIONS
*********************************************************************/
void * operator new(unsigned int size) throw (std::bad_alloc);
void operator delete(void*) throw();
void* operator new(size_t size, const std::nothrow_t&) throw ();
void operator delete(void* ptr, const std::nothrow_t&) throw ();class Pointers : public QObject
{
public:
static QList<void > instance();
static void release();
};#define MARK() Pointers::instance()->clear()
#define NUM_POINTERS() Pointers::instance()->count()/*********************************************************************
- TEST CLASS
*********************************************************************/
class UnittestOperatorTest : public QObject
{
Q_OBJECTprivate slots: void init(); void cleanup(); // Test cases void testCanary();
};
#endif // UNITTEST_OPERATORTEST
@unittest_operatortest.cpp
@
#include "unittest_operatortest.h"#include <QApplication>
#include <QtTest/QTest>
#include <QDebug>/*********************************************************************
- POINTER CLASS IMPLEMENTATION
*********************************************************************/
static QList<void > globalAllocationList = NULL;
QList<void > Pointers::instance()
{
if ( !globalAllocationList ) {
globalAllocationList = static_cast<QList<void*>*>(malloc(sizeof(new QList<void >)));
new (globalAllocationList) QList <void>;
}
return globalAllocationList;
}void Pointers::release()
{
globalAllocationList->~QList();
free(globalAllocationList);
globalAllocationList = NULL;
}/*********************************************************************
- TEST CASES
*********************************************************************/
void UnittestOperatorTest::init() {
MARK();
}void UnittestOperatorTest::cleanup() {
}void UnittestOperatorTest::testCanary() {
QVERIFY(true);// Makes sure that environment works for new and delete -operators. QCOMPARE(NUM_POINTERS(), 0); int *i = new int(2); QCOMPARE(NUM_POINTERS(), 1); delete i; QCOMPARE(NUM_POINTERS(), 0); QWidget *w = new QWidget(); QCOMPARE(NUM_POINTERS(), 1); delete w; QCOMPARE(NUM_POINTERS(), 0);
}
@main.cpp
@
#include "unittest_operatortest.h"#include <QtTest/QTest>
#include <QApplication>/*********************************************************************
- OVERRIDE CODE
*********************************************************************/
void * operator new(unsigned int size) throw (std::bad_alloc)
{
void *ptr = (void *)malloc(size);
Pointers::instance()->append(ptr);
return(ptr);
};void operator delete(void *p) throw()
{
Pointers::instance()->removeAll(p);
free(p);
};void * operator new(unsigned int size, const std::nothrow_t&) throw ()
{
void *ptr = (void *)malloc(size);
Pointers::instance()->append(ptr);
return(ptr);
};void operator delete(void *p, const std::nothrow_t&) throw()
{
Pointers::instance()->removeAll(p);
free(p);
};/*********************************************************************
- MAIN FUNCTION
*********************************************************************/
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
int ret = 0;UnittestOperatorTest testableClass; ret = QTest::qExec(&testableClass, argc, argv); return ret;
}
@ - DECLARATIONS