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.cpp
- 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);
- };
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.cpp
- void 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);
- 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
6 replies
Some more information…
This does not work:
- // test.cpp
- void 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);
- QCOMPARE(NUM_POINTERS(), 1);
- delete w;
- QCOMPARE(NUM_POINTERS(), 0); // <------ FAILS!!!???
- }
But this works:
- // test.cpp
- void 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);
- 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[])
- {
- qDebug() << ptrs;
- 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 console
- DEFINES += BUILD_QTILIB
- SOURCES += main.cpp
- SOURCES += unittest_operatortest.cpp
- HEADERS += 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 ();
- {
- public:
- static void release();
- };
- #define MARK() Pointers::instance()->clear()
- #define NUM_POINTERS() Pointers::instance()->count()
- /*********************************************************************
- * TEST CLASS
- *********************************************************************/
- {
- Q_OBJECT
- private 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
- *********************************************************************/
- {
- if ( !globalAllocationList ) {
- }
- return globalAllocationList;
- }
- void Pointers::release()
- {
- 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);
- 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[])
- {
- int ret = 0;
- UnittestOperatorTest testableClass;
- return ret;
- }
You must log in to post a reply. Not a member yet? Register here!
