Guglizás után valóban találtam ilyen megoldásokat, de elég nehezen akadtam ténylegesen működő, lefordítható megoldásra.
http://www.linuxtopia.org/online_books/programming_books/c%2B%2B_practi…
Ennek felhasználásával elkészítettem a saját egyszerű megoldásomat:
Készítünk egy saját new operátort, amelynek átadjuk az igényelt memória méreten kívül a forrás fájl nevét és a sorszámot melyek mutatják hol történt a memória foglalás.
(Nem látom hogy a kód rendesen jelenne meg pedig használtam a code tag-et így itt van egy pastebin-es megoldás: http://pastebin.com/4i5rHRkP Innen érdemes inkább leszedni a kódot.)
//*******************************************************************
// mynew.h
#ifndef MYNEW_H
#define MYNEW_H
#include <cstddef>
void* operator new(std::size_t size, const char *__file__, unsigned int __line__);
void* operator new[](std::size_t size, const char *__file__, unsigned int __line__);
void operator delete(void *ptr);
void operator delete[](void *ptr);
#define new new (__FILE__, __LINE__)
#endif // MYNEW_H
Ez a megoldás meghív egy egyszerű lefoglalás/felszabadítás nyilvántartót. Ezt természetesen tovább lehet fejleszteni szál biztosra, singleton-ra, illetve hogy felismerje a new[] és delete problémáját.
//*******************************************************************
// mynew.cpp
#include "memorytracker.h"
#include "mynew.h"
extern MemoryTracker mTracker;
#undef new
void* operator new(std::size_t size, const char *__file__, unsigned int __line__) {
void *ptr = malloc(size);
mTracker.record_alloc(reinterpret_cast<unsigned int>(ptr),__file__,__line__);
return ptr;
}
void* operator new[](std::size_t size, const char *__file__, unsigned int __line__) {
void *ptr = malloc(size);
mTracker.record_alloc(reinterpret_cast<unsigned int>(ptr),__file__,__line__);
return ptr;
}
void operator delete(void *ptr)throw()
{
mTracker.unrecord_alloc(reinterpret_cast<unsigned int>(ptr));
free(ptr);
}
void operator delete[](void *ptr)throw()
{
mTracker.unrecord_alloc(reinterpret_cast<unsigned int>(ptr));
free(ptr);
}
Íme, itt a nyilvántartó:
//*******************************************************************
// memorytracker.h
#ifndef MEMORYTRACKER_H
#define MEMORYTRACKER_H
#include <QMap>
#include <QDebug>
class MemoryTracker {
public:
~MemoryTracker();
void record_alloc(unsigned int ptr,const char *__file__,unsigned int __line__);
void unrecord_alloc(unsigned int ptr);
private:
QMap <int,QString>storage;
};
#endif // MEMORYTRACKER_H
//*******************************************************************
// memorytracker.cpp
#include "memorytracker.h"
void MemoryTracker::record_alloc(unsigned int ptr, const char *__file__, unsigned int __line__)
{
storage.insert(ptr, QString(__file__) + " Line: " + QString().number(__line__));
}
void MemoryTracker::unrecord_alloc(unsigned int ptr)
{
storage.remove(ptr);
}
MemoryTracker::~MemoryTracker()
{
foreach (QString value, storage)qDebug() << value;
}
Hogyan működik?
Egyszerű dummy osztály ellenőrizni:
//*******************************************************************
// dummy.h
#ifndef DUMMY_H
#define DUMMY_H
class dummy
{
public:
dummy();
};
#endif // DUMMY_H
//*******************************************************************
// dummy.cpp
#include "dummy.h"
#include "mynew.h" // fontos hogy utolso helyen legyen
dummy::dummy()
{
int *ptr = new int [5]; // Memory leak
}
Főprogram:
//*******************************************************************
// main.cpp
#include "memorytracker.h"
#include "dummy.h"
MemoryTracker mTracker;
#include "mynew.h"
int main(int argc, char *argv[])
{
int *p = new int[10]; // Ez ok, mert felszabadítjuk késöbb.
dummy *d = new dummy; // biza ez is memory leak!
delete[] p;
return 0;
}
Futtatáskor gyönyörűen láthatjuk a problémás helyeket!
Ui.: abban a fájlban ahol le szeretnénk cserélni a saját megoldásunkra a new operatort, csak tegyük az include blokk VÉGÉRE a #include "mynew.h"-t. Persze lényegesen lassabb így a program, tehát csak tesztelési céllal érdemes használni.
Ui2.: Blackberry alatt valami gondja van, meg at kell neznem.
Ui3.: BB alatt implementálnom kellett a new és delete operátorokat eredeti paraméterekkel is (overloading). A fordítónak szüksége volt rá. Illetve le kellett cserélnem a Qt QMap-ot saját megoldásra, lásd lejjebb.
Ui4.: Átírtam hogy lehessen Qt gui alatt használni. QApplication-ből származtatnom kellett egy saját osztályt, melynek destruktorában listázom ki a problémás memória foglalásokat.
Letölteni a
git clone https://github.com/zhanisch/DetectingMemLeak.git
Vagy ha nincs telepítve git akkor a forrás kódot a fenti címet böngészve lehet megtekinteni.
Futtatva láthatjuk hol van gond:
Starting /home/zhanisch/documents/QtProjects/build-DetectingMemLeak-Desktop_Qt_5_0_2_GCC_32bit-Debug/DetectingMemLeak...
Not relased object at: 162713376, file: ../DetectingMemLeak/mainwindow.cpp, line: 19
Not relased object at: 162711392, file: ../DetectingMemLeak/mainwindow.cpp, line: 23
/home/zhanisch/documents/QtProjects/build-DetectingMemLeak-Desktop_Qt_5_0_2_GCC_32bit-Debug/DetectingMemLeak exited with code 0
- hanischz blogja
- A hozzászóláshoz be kell jelentkezni
- 1615 megtekintés
Hozzászólások
a code taget lezárod még, kérlek?
- A hozzászóláshoz be kell jelentkezni
Persze, megcsináltam.
code és /code páros közé tettem a kódot.
- A hozzászóláshoz be kell jelentkezni
nem.
- A hozzászóláshoz be kell jelentkezni
It's not working.
- A hozzászóláshoz be kell jelentkezni
de. < code > és < /code > közé. persze szünetek nélkül
Íme:
< code >
#ifndef DUMMY_H
#define DUMMY_H
class dummy
{
public:
dummy();
};
#endif // DUMMY_H
< /code >
Gyengébbek kedvéért: szünetek nélkül.
- A hozzászóláshoz be kell jelentkezni
Akkor ird at legyszives [ code ] / [ /code] parosra. A HTML code gonosz. Koszi.
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant.
- A hozzászóláshoz be kell jelentkezni
Koszonom! Kicsit felrevezeto hogy a felajanlott tag-eknel < code > -ot latok.
- A hozzászóláshoz be kell jelentkezni
LOL, megint rossz lett.
- A hozzászóláshoz be kell jelentkezni
Trollkodás kedvéért, nem komolyan mondom:
Inkább Drupal 5 haladó technikákról kéne blogot írni :-P
- A hozzászóláshoz be kell jelentkezni
- A hozzászóláshoz be kell jelentkezni
subs
- A hozzászóláshoz be kell jelentkezni
+1
- A hozzászóláshoz be kell jelentkezni
Feliratkozni sosem késő.
- A hozzászóláshoz be kell jelentkezni