r=dp; implement some macros to help track memory leaks

This commit is contained in:
kipp%netscape.com 1999-10-04 23:36:18 +00:00
parent a5969c2c3f
commit 9b78e0fd9d
4 changed files with 330 additions and 0 deletions

View File

@ -17,8 +17,10 @@
* Netscape Communications Corporation. All Rights Reserved.
*/
#include "nsISupports.h"
#include "nsVoidArray.h"
#include "prprf.h"
#include "prlog.h"
#include "plstr.h"
#if defined(_WIN32)
#include <windows.h>
@ -542,3 +544,99 @@ nsTraceRefcnt::DemangleSymbol(const char * aSymbol,
}
#endif // __linux__
//----------------------------------------------------------------------
#ifdef DEBUG
struct CtorEntry {
const char* type;
mozCtorDtorCounter* counter;
};
nsVoidArray* nsTraceRefcnt::mCtors;
void
nsTraceRefcnt::RegisterCtor(const char* aType,
mozCtorDtorCounter* aCounterAddr)
{
if (!mCtors) {
mCtors = new nsVoidArray();
if (!mCtors) {
return;
}
}
CtorEntry* e = new CtorEntry();
if (!e) {
return;
}
e->type = aType;
e->counter = aCounterAddr;
mCtors->AppendElement(e);
}
void
nsTraceRefcnt::UnregisterCtor(const char* aType)
{
if (mCtors) {
PRInt32 i, n = mCtors->Count();
for (i = 0; i < n; i++) {
CtorEntry* e = (CtorEntry*) mCtors->ElementAt(i);
if (0 == PL_strcmp(e->type, aType)) {
delete e;
mCtors->RemoveElementAt(i);
break;
}
}
}
}
void
nsTraceRefcnt::DumpLeaks(FILE* out)
{
if (mCtors) {
PRBool haveLeaks = PR_FALSE;
PRInt32 i, n = mCtors->Count();
for (i = 0; i < n; i++) {
CtorEntry* e = (CtorEntry*) mCtors->ElementAt(i);
if (e) {
mozCtorDtorCounter* cdc = e->counter;
if (cdc) {
if (cdc->ctors != cdc->dtors) {
haveLeaks = PR_TRUE;
break;
}
}
}
}
if (haveLeaks) {
fprintf(out, "*** There are memory leaks:\n");
fprintf(out, "%-40s %-15s %s\n", "Type", "# created", "# leaked");
fprintf(out, "%-40s %-15s %s\n", "----", "---------", "--------");
for (i = 0; i < n; i++) {
CtorEntry* e = (CtorEntry*) mCtors->ElementAt(i);
if (e && e->counter) {
mozCtorDtorCounter* cdc = e->counter;
if (cdc->ctors != cdc->dtors) {
fprintf(out, "%-40s %-15d %d\n", e->type, cdc->ctors,
cdc->ctors - cdc->dtors);
}
}
}
}
}
}
void
nsTraceRefcnt::FlushCtorRegistry(void)
{
if (mCtors) {
PRInt32 i, n = mCtors->Count();
for (i = 0; i < n; i++) {
CtorEntry* e = (CtorEntry*) mCtors->ElementAt(i);
delete e;
}
delete mCtors;
}
}
#endif /* DEBUG */

View File

@ -20,6 +20,16 @@
#define nsTraceRefcnt_h___
#include "nsCom.h"
#include <stdio.h>
class nsVoidArray;
#ifdef DEBUG
struct mozCtorDtorCounter {
PRInt32 ctors;
PRInt32 dtors;
};
#endif
/**
* This class is used to support tracing (and logging using nspr) of
@ -71,6 +81,63 @@ public:
const char* aFile,
int aLine);
#ifdef DEBUG
/**
* Register a constructor with the xpcom library. This records the
* type name and the address of the counter so that later on when
* DumpLeaks is called, we can print out those objects ctors whose
* counter is not zero (the ones that have live object references
* still out there)
*/
static NS_COM void RegisterCtor(const char* aType,
mozCtorDtorCounter* aCounterAddr);
static NS_COM void UnregisterCtor(const char* aType);
/**
* Dump the leaking constructors out.
*/
static NS_COM void DumpLeaks(FILE* out);
/**
* Erase the ctor registration data.
*/
static NS_COM void FlushCtorRegistry(void);
#endif
protected:
#ifdef DEBUG
static nsVoidArray* mCtors;
#endif
};
//----------------------------------------------------------------------
#ifdef DEBUG
#define MOZ_DECL_CTOR(_type) \
static mozCtorDtorCounter gCounter_##_type
#define MOZ_CTOR(_type) \
PR_BEGIN_MACRO \
if (0 == gCounter_##_type . ctors) { \
nsTraceRefcnt::RegisterCtor(#_type, &gCounter_##_type); \
} \
gCounter_##_type . ctors++; \
PR_END_MACRO
#define MOZ_DTOR(_type) \
PR_BEGIN_MACRO \
gCounter_##_type . dtors ++; \
PR_END_MACRO
#else
#define MOZ_REG_CTOR(_type,_counter)
#define MOZ_DECL_CTOR_(type)
#define MOZ_CTOR(_type)
#define MOZ_DTOR(_type)
#endif /* DEBUG */
#endif /* nsTraceRefcnt_h___ */

View File

@ -17,8 +17,10 @@
* Netscape Communications Corporation. All Rights Reserved.
*/
#include "nsISupports.h"
#include "nsVoidArray.h"
#include "prprf.h"
#include "prlog.h"
#include "plstr.h"
#if defined(_WIN32)
#include <windows.h>
@ -542,3 +544,99 @@ nsTraceRefcnt::DemangleSymbol(const char * aSymbol,
}
#endif // __linux__
//----------------------------------------------------------------------
#ifdef DEBUG
struct CtorEntry {
const char* type;
mozCtorDtorCounter* counter;
};
nsVoidArray* nsTraceRefcnt::mCtors;
void
nsTraceRefcnt::RegisterCtor(const char* aType,
mozCtorDtorCounter* aCounterAddr)
{
if (!mCtors) {
mCtors = new nsVoidArray();
if (!mCtors) {
return;
}
}
CtorEntry* e = new CtorEntry();
if (!e) {
return;
}
e->type = aType;
e->counter = aCounterAddr;
mCtors->AppendElement(e);
}
void
nsTraceRefcnt::UnregisterCtor(const char* aType)
{
if (mCtors) {
PRInt32 i, n = mCtors->Count();
for (i = 0; i < n; i++) {
CtorEntry* e = (CtorEntry*) mCtors->ElementAt(i);
if (0 == PL_strcmp(e->type, aType)) {
delete e;
mCtors->RemoveElementAt(i);
break;
}
}
}
}
void
nsTraceRefcnt::DumpLeaks(FILE* out)
{
if (mCtors) {
PRBool haveLeaks = PR_FALSE;
PRInt32 i, n = mCtors->Count();
for (i = 0; i < n; i++) {
CtorEntry* e = (CtorEntry*) mCtors->ElementAt(i);
if (e) {
mozCtorDtorCounter* cdc = e->counter;
if (cdc) {
if (cdc->ctors != cdc->dtors) {
haveLeaks = PR_TRUE;
break;
}
}
}
}
if (haveLeaks) {
fprintf(out, "*** There are memory leaks:\n");
fprintf(out, "%-40s %-15s %s\n", "Type", "# created", "# leaked");
fprintf(out, "%-40s %-15s %s\n", "----", "---------", "--------");
for (i = 0; i < n; i++) {
CtorEntry* e = (CtorEntry*) mCtors->ElementAt(i);
if (e && e->counter) {
mozCtorDtorCounter* cdc = e->counter;
if (cdc->ctors != cdc->dtors) {
fprintf(out, "%-40s %-15d %d\n", e->type, cdc->ctors,
cdc->ctors - cdc->dtors);
}
}
}
}
}
}
void
nsTraceRefcnt::FlushCtorRegistry(void)
{
if (mCtors) {
PRInt32 i, n = mCtors->Count();
for (i = 0; i < n; i++) {
CtorEntry* e = (CtorEntry*) mCtors->ElementAt(i);
delete e;
}
delete mCtors;
}
}
#endif /* DEBUG */

View File

@ -20,6 +20,16 @@
#define nsTraceRefcnt_h___
#include "nsCom.h"
#include <stdio.h>
class nsVoidArray;
#ifdef DEBUG
struct mozCtorDtorCounter {
PRInt32 ctors;
PRInt32 dtors;
};
#endif
/**
* This class is used to support tracing (and logging using nspr) of
@ -71,6 +81,63 @@ public:
const char* aFile,
int aLine);
#ifdef DEBUG
/**
* Register a constructor with the xpcom library. This records the
* type name and the address of the counter so that later on when
* DumpLeaks is called, we can print out those objects ctors whose
* counter is not zero (the ones that have live object references
* still out there)
*/
static NS_COM void RegisterCtor(const char* aType,
mozCtorDtorCounter* aCounterAddr);
static NS_COM void UnregisterCtor(const char* aType);
/**
* Dump the leaking constructors out.
*/
static NS_COM void DumpLeaks(FILE* out);
/**
* Erase the ctor registration data.
*/
static NS_COM void FlushCtorRegistry(void);
#endif
protected:
#ifdef DEBUG
static nsVoidArray* mCtors;
#endif
};
//----------------------------------------------------------------------
#ifdef DEBUG
#define MOZ_DECL_CTOR(_type) \
static mozCtorDtorCounter gCounter_##_type
#define MOZ_CTOR(_type) \
PR_BEGIN_MACRO \
if (0 == gCounter_##_type . ctors) { \
nsTraceRefcnt::RegisterCtor(#_type, &gCounter_##_type); \
} \
gCounter_##_type . ctors++; \
PR_END_MACRO
#define MOZ_DTOR(_type) \
PR_BEGIN_MACRO \
gCounter_##_type . dtors ++; \
PR_END_MACRO
#else
#define MOZ_REG_CTOR(_type,_counter)
#define MOZ_DECL_CTOR_(type)
#define MOZ_CTOR(_type)
#define MOZ_DTOR(_type)
#endif /* DEBUG */
#endif /* nsTraceRefcnt_h___ */