21 #include "internal/berryCTKPluginActivator.h" 26 #include <Poco/Bugcheck.h> 27 #include <Poco/NumberParser.h> 28 #include <Poco/DOM/NodeList.h> 29 #include <Poco/DOM/DOMParser.h> 30 #include <Poco/DOM/Document.h> 31 #include <Poco/DOM/Element.h> 32 #include <Poco/DOM/DOMWriter.h> 33 #include <Poco/SAX/InputSource.h> 34 #include <Poco/SAX/SAXException.h> 36 #include <Poco/FileStream.h> 47 const QString DebugUtil::DEBUG_UTIL_XML =
"debugutil.xml";
48 const QString DebugUtil::DEBUGUTIL_TAG =
"debugutil";
49 const QString DebugUtil::TRACEOBJECT_TAG =
"traceObject";
50 const QString DebugUtil::TRACECLASS_TAG =
"traceClass";
51 const QString DebugUtil::ID_ATTR =
"id";
52 const QString DebugUtil::NAME_ATTR =
"name";
54 QHash<quint32, QList<unsigned int> > DebugUtil::m_TraceIdToSmartPointerMap;
55 QHash<quint32, const Object*> DebugUtil::m_TraceIdToObjectMap;
56 QSet<unsigned int> DebugUtil::m_TracedObjects;
57 QSet<QString> DebugUtil::m_TracedClasses;
59 class NotClassName:
public std::unary_function<const Object*, bool>
65 NotClassName(
const QString& s) :
69 bool operator()(
const Object* entry)
const 78 return &breakpointManager;
81 #ifdef BLUEBERRY_DEBUG_SMARTPOINTER 84 BERRY_INFO <<
"Tracing enabled for: " <<
object->GetTraceId() << std::endl;
85 m_TracedObjects.insert(object->GetTraceId());
94 #ifdef BLUEBERRY_DEBUG_SMARTPOINTER 97 BERRY_INFO <<
"Tracing enabled for: " << traceId << std::endl;
98 m_TracedObjects.insert(traceId);
99 TraceIdToObjectType::ConstIterator i = m_TraceIdToObjectMap.find(traceId);
100 if (i != m_TraceIdToObjectMap.end())
111 #ifdef BLUEBERRY_DEBUG_SMARTPOINTER 114 BERRY_INFO <<
"Tracing enabled for: " << className << std::endl;
115 m_TracedClasses.insert(className);
124 #ifdef BLUEBERRY_DEBUG_SMARTPOINTER 128 BERRY_INFO <<
"Tracing stopped for: " << traceId << std::endl;
129 m_TracedObjects.remove(traceId);
130 TraceIdToObjectType::ConstIterator i = m_TraceIdToObjectMap.find(traceId);
131 if (i != m_TraceIdToObjectMap.end())
142 #ifdef BLUEBERRY_DEBUG_SMARTPOINTER 145 BERRY_INFO <<
"Tracing stopped for: " << obj->GetTraceId() << std::endl;
146 m_TracedObjects.remove(obj->GetTraceId());
155 #ifdef BLUEBERRY_DEBUG_SMARTPOINTER 158 BERRY_INFO <<
"Tracing stopped for: " << className << std::endl;
159 m_TracedClasses.remove(className);
168 #ifdef BLUEBERRY_DEBUG_SMARTPOINTER 171 if (m_TracedObjects.find(object->GetTraceId()) != m_TracedObjects.end())
174 if (m_TracedClasses.find(object->
GetClassName()) != m_TracedClasses.end())
186 #ifdef BLUEBERRY_DEBUG_SMARTPOINTER 189 if (m_TracedObjects.find(traceId) != m_TracedObjects.end())
192 TraceIdToObjectType::Iterator it = m_TraceIdToObjectMap.find(traceId);
193 if (it != m_TraceIdToObjectMap.end())
195 if (m_TracedClasses.find(it.value()->GetClassName()) != m_TracedClasses.end())
208 #ifdef BLUEBERRY_DEBUG_SMARTPOINTER 211 return m_TracedClasses.find(className) != m_TracedClasses.end();
222 return m_TracedObjects;
227 return m_TraceIdToObjectMap[traceId];
230 #ifdef BLUEBERRY_DEBUG_SMARTPOINTER 232 const Object* objectPointer,
const QList<unsigned int>& excludeList)
234 Q_ASSERT(objectPointer != 0);
235 QList<unsigned int> ids = m_TraceIdToSmartPointerMap[objectPointer->GetTraceId()];
236 for (QList<unsigned int>::const_iterator iter = excludeList.begin();
237 iter != excludeList.end(); ++iter)
238 ids.removeAll(*iter);
243 const Object* ,
const QList<unsigned int>& )
245 return QList<unsigned int>();
251 return m_TraceIdToObjectMap.values();
256 qDebug() <<
"SmartPointer IDs [ ";
257 if (IsTraced(objectPointer))
259 QList<unsigned int> ids = GetSmartPointerIDs(objectPointer, excludeList);
260 for (QList<unsigned int>::const_iterator iter = ids.begin();
261 iter != ids.end(); ++iter)
263 qDebug() << *iter <<
" ";
285 m_TraceIdToObjectMap.clear();
286 m_TraceIdToSmartPointerMap.clear();
287 m_TracedObjects.clear();
294 for (
auto object : m_TraceIdToObjectMap)
297 if (!names.isEmpty())
299 std::cout << std::endl << std::endl <<
"#########################################################" << std::endl;
300 std::cout <<
"######## berry::Object leakage summary: ########" << std::endl << std::endl;
302 for (QSet<QString>::const_iterator i = names.begin();
303 i != names.end(); ++i)
305 PrintObjectSummary(*i, details);
306 if (details) std::cout << std::endl;
309 std::cout << std::endl <<
"#########################################################" << std::endl << std::endl;
312 return !names.isEmpty();
317 TraceIdToObjectType::ConstIterator endIter =
318 std::remove_if(m_TraceIdToObjectMap.begin(), m_TraceIdToObjectMap.end(), NotClassName(className));
320 qDebug() <<
"Class:" << className;
321 if (details) std::cout << std::endl;
323 std::size_t count = 0;
324 for (TraceIdToObjectType::ConstIterator iter = m_TraceIdToObjectMap.begin();
325 iter != endIter; ++iter, ++count)
329 qDebug() << (*(iter.value()));
330 PrintSmartPointerIDs(iter.value());
333 qDebug() <<
"(" << count <<
" instances)\n";
339 static unsigned int counter = 0;
343 #ifdef BLUEBERRY_DEBUG_SMARTPOINTER 346 poco_assert(objectPointer != 0);
348 m_TraceIdToSmartPointerMap[objectPointer->GetTraceId()].removeAll(smartPointerId);
357 #ifdef BLUEBERRY_DEBUG_SMARTPOINTER 360 poco_assert(objectPointer != 0);
362 if (m_TracedClasses.find(objectPointer->
GetClassName()) != m_TracedClasses.end() ||
363 m_TracedObjects.find(objectPointer->GetTraceId()) != m_TracedObjects.end())
365 m_TraceIdToSmartPointerMap[objectPointer->GetTraceId()].push_back(smartPointerId);
369 if (GetBreakpointManager()->BreakAtSmartpointer(smartPointerId))
370 poco_debugger_msg(
"SmartPointer Breakpoint reached");
378 #ifdef BLUEBERRY_DEBUG_SMARTPOINTER 381 m_TraceIdToObjectMap.insert(objectPointer->GetTraceId(), objectPointer);
384 if (GetBreakpointManager()->BreakAtObject(objectPointer->GetTraceId()))
386 std::string msg =
"SmartPointer Breakpoint reached for ";
388 poco_debugger_msg(msg.c_str());
397 #ifdef BLUEBERRY_DEBUG_SMARTPOINTER 400 m_TraceIdToObjectMap.remove(objectPointer->GetTraceId());
409 bool DebugUtil::GetPersistencePath(QDir& path)
411 QFileInfo statePath = CTKPluginActivator::getPluginContext()->getDataFile(QString());
412 path = statePath.absoluteFilePath();
418 QString saveFile = path.absoluteFilePath(DEBUG_UTIL_XML);
420 auto doc =
new Poco::XML::Document();
421 Poco::XML::Element* debugutil = doc->createElement(DEBUGUTIL_TAG.toStdString());
422 doc->appendChild(debugutil)->release();
424 for (QSet<unsigned int>::const_iterator i = m_TracedObjects.begin();
425 i != m_TracedObjects.end(); ++i)
427 Poco::XML::Element* traceObject = doc->createElement(TRACEOBJECT_TAG.toStdString());
428 debugutil->appendChild(traceObject)->release();
429 traceObject->setAttribute(ID_ATTR.toStdString(), QString::number(*i).toStdString());
432 for (QSet<QString>::const_iterator i = m_TracedClasses.begin();
433 i != m_TracedClasses.end(); ++i)
435 Poco::XML::Element* traceClass = doc->createElement(TRACECLASS_TAG.toStdString());
436 debugutil->appendChild(traceClass)->release();
437 traceClass->setAttribute(NAME_ATTR.toStdString(), i->toStdString());
442 Poco::FileOutputStream writer(saveFile.toStdString());
443 Poco::XML::DOMWriter out;
445 out.writeNode(writer, doc);
451 GetBreakpointManager()->SaveState(saveBM);
453 catch (Poco::FileException& e)
462 QString restoreFile = path.absoluteFilePath(DEBUG_UTIL_XML);
466 Poco::XML::DOMParser parser;
468 Poco::FileInputStream reader(restoreFile.toStdString());
469 Poco::XML::InputSource source(reader);
472 Poco::XML::Document* doc = parser.parse(&source);
473 Poco::XML::Element* debugutil = doc->documentElement();
478 Poco::XML::NodeList* elementList = debugutil->getElementsByTagName(TRACEOBJECT_TAG.toStdString());
479 for (std::size_t i = 0; i < elementList->length(); i++)
481 Poco::XML::Element* elem =
482 dynamic_cast<Poco::XML::Element*
> (elementList->item(static_cast<unsigned long>(i)));
484 if (!elem->hasAttribute(ID_ATTR.toStdString()))
continue;
486 const std::string& attr = elem->getAttribute(ID_ATTR.toStdString());
491 traceId = Poco::NumberParser::parse(attr);
493 catch (
const Poco::SyntaxException& e)
500 elementList->release();
503 elementList = debugutil->getElementsByTagName(TRACECLASS_TAG.toStdString());
504 for (std::size_t i = 0; i < elementList->length(); i++)
506 Poco::XML::Element* elem =
507 dynamic_cast<Poco::XML::Element*
> (elementList->item(static_cast<unsigned long>(i)));
509 if (!elem->hasAttribute(NAME_ATTR.toStdString()))
continue;
511 const std::string& traceClass = elem->getAttribute(NAME_ATTR.toStdString());
512 if (!traceClass.empty())
515 elementList->release();
520 catch (Poco::XML::SAXParseException& e)
524 catch (Poco::FileNotFoundException&)
528 catch (Poco::FileException& e)
virtual QString GetClassName() const
static void RemoveObjectListener(IDebugObjectListener *listener)
static void UnregisterSmartPointer(unsigned int smartPointerId, const Object *objectPointer)
SmartPointerEventType spDestroyedEvent
Light weight base class for most BlueBerry classes.
void AddListener(IDebugObjectListener *listener)
static const Object * GetObject(unsigned int traceId)
static void TraceClass(const QString &className)
static QList< unsigned int > GetSmartPointerIDs(const Object *objectPointer, const QList< unsigned int > &excludeList=QList< unsigned int >())
static unsigned int & GetSmartPointerCounter()
static void RestoreState(const QDir &path)
static void ResetObjectSummary()
static IDebugObjectListener::Events _G_ObjectEvents
static const std::string BREAKPOINTS_XML
TracingEventType objTracingEvent
static void RegisterSmartPointer(unsigned int smartPointerId, const Object *objectPointer, bool recordStack=false)
static QSet< unsigned int > GetTracedObjects()
static bool IsTraced(const Object *object)
static void RegisterObject(const Object *objectPointer)
ObjectEventType objCreatedEvent
static bool PrintObjectSummary(bool details=false)
ObjectEventType objDestroyedEvent
static DebugBreakpointManager * GetBreakpointManager()
static void PrintSmartPointerIDs(const Object *objectPointer, const QList< unsigned int > &excludeList=QList< unsigned int >())
static QList< const Object * > GetRegisteredObjects()
static void AddObjectListener(IDebugObjectListener *listener)
static void SaveState(const QDir &path)
void RemoveListener(IDebugObjectListener *listener)
SmartPointerEventType spCreatedEvent
static void StopTracing(unsigned int traceId)
static void TraceObject(const Object *)
static void UnregisterObject(const Object *objectPointer)