📄 vglog.cpp
字号:
/* summ the leaks for each leak kind */ VgErrorList::iterator it; for ( it = errs.begin(); it != errs.end(); ++it ) { VgError err = *it; QDomNodeList err_details = err.childNodes(); assert( err_details.count() >= 6 ); QString bytes = err_details.item( 4 ).toElement().text(); QString blocks = err_details.item( 5 ).toElement().text(); VgError::LeakKind kind = err.leakKind(); assert( kind < VgError::NUM_LKS ); lk_bytes [ kind ] += bytes.toULong(); lk_blocks[ kind ] += blocks.toULong(); } QString output_str = "LEAK SUMMARY\n"; int field_width = VgError::leakDesc(VgError::UNREACHED).length(); for (int i=0; i<VgError::NUM_LKS; i++) { if (i == VgError::INDIRECT && lk_blocks[i] == 0) continue; output_str += QString(" %1 %2 bytes in %3 blocks\n") .arg( VgError::leakDesc( (VgError::LeakKind)i ), field_width ) .arg( lk_bytes[i] ) .arg( lk_blocks[i] ); } return output_str;}/* print entire log to plain text string, a-la valgrind non-xml output */QString VgLog::toPlainTxt(){ QString output_str; output_str = preamble().toPlainTxt() + "\n"; VgErrorList errs = errors(); VgErrorList::iterator it; for ( it = errs.begin(); it != errs.end(); ++it ) { /* find count from matching pair in errorcount */ QString count = errorcounts().getCount( *it ).getContent(); if (count == "") count = "?"; output_str += "Occurred " + count + " times:\n"; output_str += (*it).toPlainTxt(); } output_str += plainTxtErrorSummary(); errs = leaks(); for ( it = errs.begin(); it != errs.end(); ++it ) { output_str += (*it).toPlainTxt(); } output_str += plainTxtLeakSummary(); return output_str;}/* xml string - with \n between each top-level chunk - reimplementation of QDomDocument::toString()*/QString VgLog::toString( int ){ if (log.isNull()) return ""; QString str; QTextStream s( str, IO_WriteOnly ); s << log.firstChild() << "\n"; QString doc_elem = docroot().nodeName(); s << "<" << doc_elem << ">\n\n"; QDomNode n = docroot().firstChild(); for ( ; !n.isNull(); n=n.nextSibling() ) { n.save( s, 2 ); s << "\n"; } s << "</" << doc_elem << ">\n"; return str;}bool VgLog::mergeErrors( VgErrorList sErrors, VgErrCounts sErrCounts ){ VgErrCounts mErrCounts = errorcounts(); vklmPrint( 2, "--- update matches (n=%d) --- ", sErrors.count()); /* --- find matches: update master err, delete slave err --- */ /* --- for each error in master --- */ VgErrorList errs = errors(); VgErrorList::Iterator mIt; for ( mIt = errs.begin(); mIt != errs.end(); ++mIt ) { VgError mErr = (VgError&)(*mIt); vklmPrint( 2, "master err: '%s'", mErr.unique().latin1()); vklmPrint( 3, " " ); /* get master errorcount for this error */ VgElement mCount = mErrCounts.getCount( mErr ); if (mCount.isNull()) { vklmPrint( 0, "error: no matching master errorcount\n" ); return false; } /* --- for each error in slave --- */ VgErrorList::Iterator sIt; for ( sIt = sErrors.begin(); sIt != sErrors.end(); ++sIt ) { VgError sErr = *sIt; vklmPrint( 2, "slave err: '%s'", sErr.unique().latin1() ); /* get slave errorcount for this error */ VgElement sCount = sErrCounts.getCount( sErr ); if (sCount.isNull()) { vklmPrint( 0, "error: no matching slave errorcount" ); return false; } if ( mErr == sErr ) { vklmPrint( 2, "=> matched" ); /* --- master count += slave count --- */ if ( ! mCount.updateCount( sCount ) ) { vklmPrint( 0, "error: failed master errorcount update" ); return false; } /* --- remove error from slave list --- */ sIt = sErrors.remove( sIt ); sIt--; /* NOTE: not simply break'ing, as we can't guarantee there isn't another slave error that the same master error would match. This implies our error-matching heuristic isn't the same as valgrind's, i.e. match(slaveErr1, slaveErr2) may be true. CAB: Q: Why is it better to continue here? If we miss a potential second match to current master error, it'll be appended anyway. Neither way is entirely accurate, but break'ing would be faster, especially if can expect errors in similar order. */ } vklmPrint( 3, " " ); } vklmPrint( 2, " "); } vklmPrint( 2, "--- append non-matches (n=%d) --- ", sErrors.count() ); /* if no errcounts, and sErrors > 0, create empty errcounts */ if ( mErrCounts.isNull() && sErrors.count() > 0 ) { vklmPrint( 3, "creating new errcounts node" ); /* create <errorcounts/> */ QDomElement ec = log.createElement( "errorcounts" ); /* and insert before status_finished */ docroot().insertBefore( ec, status_end() ); } /* --- append remaining slave errors to master --- */ VgErrorList::Iterator sIt; for ( sIt = sErrors.begin(); sIt != sErrors.end(); ++sIt ) { VgError sErr = *sIt; vklmPrint( 2, "appending slave err: '%s'", sErr.unique().latin1() ); /* get slave errorcount::pair for this error */ VgElement sCount = sErrCounts.getCount( sErr ); QDomNode sPair = sCount.parentNode(); if (sPair.isNull()) { vklmPrint( 0, "error: no matching slave errorcount" ); return false; } /* --- append slave error to master, before last errcounts --- */ docroot().insertBefore( sErr, mErrCounts ); /* --- append slave errorcount to master --- */ mErrCounts.appendChild( sPair ); } return true;}bool VgLog::mergeLeakErrors( VgErrorList sLeakErrors ){ vklmPrint( 2, "--- update matches (n=%d) ---", sLeakErrors.count() ); /* --- for each leak in master --- */ VgErrorList errs = leaks(); VgErrorList::Iterator mIt; for ( mIt = errs.begin(); mIt != errs.end(); ++mIt ) { VgError mErr = (VgError&)(*mIt); vklmPrint( 2, "master leak: '%s'", mErr.unique().latin1() ); vklmPrint( 3, " " ); /* --- for each leak in slave --- */ VgErrorList::Iterator sIt; for ( sIt = sLeakErrors.begin(); sIt != sLeakErrors.end(); ++sIt ) { VgError sErr = (VgError&)(*sIt); vklmPrint( 2, "slave leak: '%s'", sErr.unique().latin1() ); if ( mErr == sErr ) { vklmPrint( 2, "=> matched" ); /* --- update master leakedBytes, leakedBlocks, what str --- */ if ( ! mErr.updateLeakErr( sErr ) ) { vklmPrint( 0, "error: failed to update master leak error" ); return false; } /* --- remove error from slave list --- */ sIt = sLeakErrors.remove( sIt ); sIt--; } vklmPrint( 3, " " ); } vklmPrint( 2, " "); } vklmPrint( 2, "--- append non-matches (n=%d) ---", sLeakErrors.count() ); /* --- append remaining slave leaks to master --- */ VgErrorList::Iterator sIt; for ( sIt = sLeakErrors.begin(); sIt != sLeakErrors.end(); ++sIt ) { vklmPrint( 2, "appending slave leak: '%s'", (*sIt).unique().latin1() ); docroot().appendChild( *sIt ); } return true;}bool VgLog::mergeSuppCounts( VgSuppCounts sSuppCnts ){ /* deep copy so we can delete from it safely */ QDomNode sSuppCnts_copy = sSuppCnts.cloneNode(); VgSuppCounts sSuppCounts = (VgSuppCounts&)sSuppCnts_copy; VgSuppCounts mSuppCounts = suppcounts(); vklmPrint( 2, "--- update matches (n=%d) ---", sSuppCounts.childNodes().count() ); /* --- for each suppcount::pair in master --- */ QDomElement m = mSuppCounts.firstChild().toElement(); for( ; !m.isNull(); m = m.nextSibling().toElement() ) { VgElement mPair = (VgElement&)m; QString mStr = mPair.getFirstElem( "name" ).text(); VgElement mCount = mPair.getFirstElem( "count" ); vklmPrint( 2, "master suppcount pair: '%s'", mStr.latin1() ); QDomElement s = sSuppCounts.firstChild().toElement(); for( ; !s.isNull(); s = s.nextSibling().toElement() ) { VgElement sPair = (VgElement&)s; QString sStr = mPair.getFirstElem( "name" ).text(); vklmPrint( 2, "slave suppcount pair: '%s'", sStr.latin1() ); if ( mStr == sStr ) { /* matching pair */ vklmPrint( 2, "=> matched"); VgElement sCount = sPair.getFirstElem( "count" ); /* --- master pair::count += slave pair::count --- */ if ( ! mCount.updateCount( sCount ) ) { vklmPrint( 0, "error: failed master suppcount update" ); return false; } /* --- remove err from node --- */ sSuppCounts.removeChild( sPair ); /* can only be one match, so just go to next mPair */ break; } vklmPrint( 2, " " ); } vklmPrint( 2, " " ); } vklmPrint( 2, "--- append non-matches (n=%d) ---", sSuppCounts.childNodes().count() ); /* --- append remaining slave suppcount::pairs to master --- */ QDomElement s = sSuppCounts.firstChild().toElement(); for( ; !s.isNull(); s = s.nextSibling().toElement() ) { mSuppCounts.appendChild( s ); } return true;}bool VgLog::merge( VgLog& slave ){ /* clean master of leaks before status_end */ QDomElement e = docroot().firstChild().toElement(); for ( ; !e.isNull(); e=e.nextSibling().toElement() ) { /* quit after status == FINISHED */ if (e.tagName() == "status") { if (((VgStatus&)e).state() == VgStatus::FINISHED) break; } else if (e.tagName() == "error") { VgError err = (VgError&)e; if (err.isLeak()) { e=e.previousSibling().toElement(); docroot().removeChild( err ); } } } /* clean slave of leaks before status_end */ e = slave.docroot().firstChild().toElement(); for ( ; !e.isNull(); e=e.nextSibling().toElement() ) { /* quit after status == FINISHED */ if (e.tagName() == "status") { if (((VgStatus&)e).state() == VgStatus::FINISHED) break; } else if (e.tagName() == "error") { VgError err = (VgError&)e; if (err.isLeak()) { e=e.previousSibling().toElement(); docroot().removeChild( err ); } } } /* check the same tool was used */ if (slave.tool().text() != tool().text()) { vklmPrintErr( "Different tool used for this logfile" ); return false; } /* check the same binary was used */ QDomElement sExe = slave.args().getFirstElem( "argv" ).getFirstElem( "exe" ); QDomElement mExe = args().getFirstElem( "argv" ).getFirstElem( "exe" ); if (sExe.text() != mExe.text()) { vklmPrintErr( "Different executable used for this logfile" ); return false; } /* merge errors */ vklmPrint( 2, " " ); vklmPrint( 2, "=== MERGE ERRORS ===" ); vklmPrint( 2, " " ); VgErrorList sErrors = slave.errors(); if ( sErrors.count() != 0) { if ( ! mergeErrors( slave.errors(), slave.errorcounts() ) ) return false; } else { vklmPrint( 2, "no errors to merge" ); } /* merge suppcounts */ vklmPrint( 2, " " ); vklmPrint( 2, "=== MERGE SUPPCOUNTS ===" ); vklmPrint( 2, " " ); VgSuppCounts sSuppCounts = slave.suppcounts(); if ( sSuppCounts.childNodes().count() != 0) { if ( ! mergeSuppCounts( sSuppCounts ) ) return false; } else { vklmPrint( 2, "no suppcounts to merge" ); } /* merge leaks */ vklmPrint( 2, " " ); vklmPrint( 2, "=== MERGE LEAKS ===" ); vklmPrint( 2, " " ); VgErrorList sLeakErrors = slave.leaks(); if ( sLeakErrors.count() != 0) { if ( ! mergeLeakErrors( sLeakErrors ) ) return false; } else { vklmPrint( 2, "no leak errors to merge" ); } vklmPrint( 2, " " ); return true;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -