10#include <QMutexLocker>
11#include <QGlobalStatic>
16#define IGNORE_MEMENTO_ITEM
26#ifdef HAVE_MEMORY_LEAK_TRACKER
33 BacktraceInfo() : trace(0), size(0) {
42#define BACKTRACE_SIZE 10
46#ifdef HAVE_BACKTRACE_SUPPORT
47#define MAKE_BACKTRACEINFO \
48 BacktraceInfo* info = new BacktraceInfo; \
49 info->trace = new void*[BACKTRACE_SIZE]; \
50 int n = backtrace(info->trace, BACKTRACE_SIZE); \
53#define MAKE_BACKTRACEINFO \
54 BacktraceInfo* info = 0;
58 QHash<const void*, BacktraceInfo*> infos;
62struct KisMemoryLeakTracker::Private {
63 QHash<const void*, WhatInfo > whatWhoWhen;
64 template<
typename _T_>
65 void dumpReferencedObjectsAndDelete(QHash<const _T_*, WhatInfo >&,
bool _delete);
70void KisMemoryLeakTracker::Private::dumpReferencedObjectsAndDelete(QHash<const _T_*, WhatInfo >& map,
bool _delete)
73 for (
typename QHash<const _T_*, WhatInfo >::iterator it = map.begin();
74 it != map.end(); ++it) {
75 qWarning() <<
"Object " << it.key() <<
"(" << it.value().name <<
") is still referenced by " << it.value().infos.size() <<
" objects:";
76 for (QHash<const void*, BacktraceInfo*>::iterator it2 = it.value().infos.begin();
77 it2 != it.value().infos.end(); ++it2) {
78 qWarning() <<
"Referenced by " << it2.key() <<
" at:";
79#ifdef HAVE_BACKTRACE_SUPPORT
80 BacktraceInfo* info = it2.value();
81 char** strings = backtrace_symbols(info->trace, info->size);
82 for (
int i = 0; i < info->size; ++i) {
83 qWarning() << strings[i];
91 qWarning() <<
"Enable backtrace support by running 'cmake -DHAVE_BACKTRACE_SUPPORT=ON'";
94 qWarning() <<
"=====";
104 if (
d->whatWhoWhen.isEmpty()) {
105 qInfo() <<
"No leak detected.";
107 qWarning() <<
"****************************************";
108 qWarning() << (
d->whatWhoWhen.size()) <<
" leaks have been detected";
109 d->dumpReferencedObjectsAndDelete(
d->whatWhoWhen,
true);
110 qWarning() <<
"****************************************";
112 qFatal(
"Leaks have been detected... fix krita.");
120 if(what == 0x0)
return;
122 QMutexLocker l(&
d->m);
124 if (whatName == 0 || ( strcmp(whatName,
"PK13KisSharedData") != 0
126 && strcmp(whatName,
"PK14KisMementoItem") != 0
129 && strcmp(whatName,
"PK7KisTile") != 0
133 d->whatWhoWhen[what].infos[bywho] = info;
135 d->whatWhoWhen[what].name = whatName;
142 QMutexLocker l(&
d->m);
143 if (
d->whatWhoWhen.contains(what)) {
144 QHash<const void*, BacktraceInfo*>& whoWhen =
d->whatWhoWhen[what].infos;
145 delete whoWhen[bywho];
146 whoWhen.remove(bywho);
147 if (whoWhen.isEmpty()) {
148 d->whatWhoWhen.remove(what);
155 qWarning() <<
"****************************************";
156 qWarning() << (
d->whatWhoWhen.size()) <<
" objects are currently referenced";
157 d->dumpReferencedObjectsAndDelete(
d->whatWhoWhen,
false);
158 qWarning() <<
"****************************************";
163 QMutexLocker l(&
d->m);
164 if (!
d->whatWhoWhen.contains(what)) {
165 qWarning() <<
"Object " << what <<
" is not tracked";
169 WhatInfo& info =
d->whatWhoWhen[what];
170 qInfo() <<
"Object " << what <<
"(" << info.name <<
") is still referenced by " << info.infos.size() <<
" objects:";
171 for (QHash<const void*, BacktraceInfo*>::iterator it2 = info.infos.begin();
172 it2 != info.infos.end(); ++it2) {
173 qInfo() <<
"Referenced by " << it2.key() <<
" at:";
174#ifdef HAVE_BACKTRACE_SUPPORT
175 BacktraceInfo* info = it2.value();
176 char** strings = backtrace_symbols(info->trace, info->size);
177 for (
int i = 0; i < info->size; ++i) {
178 qInfo() << strings[i];
181 qInfo() <<
"Enable backtrace support in kis_memory_leak_tracker.cpp";
188#error "Hum, no memory leak tracker for your platform"
Q_GLOBAL_STATIC(KisStoragePluginRegistry, s_instance)
PythonPluginManager * instance
void dereference(const void *what, const void *bywho)
void reference(const void *what, const void *bywho, const char *whatName=0)
#define IGNORE_MEMENTO_ITEM
const char * name(StandardAction id)
int size(const Forest< T > &forest)