http://www.fourmilab.ch/smartall/
-
+
Version $Id$
*/
#undef free
/* We normally turn off debugging here.
- * If you want it, simply #ifdef all the
+ * If you want it, simply #ifdef all the
* following off.
*/
#undef Dmsg1
#define Dmsg2(l,f,a1,a2)
#define Dmsg3(l,f,a1,a2,a3)
#define Dmsg4(l,f,a1,a2,a3,a4)
-
+uint64_t sm_max_bytes = 0;
+uint64_t sm_bytes = 0;
+uint32_t sm_max_buffers = 0;
+uint32_t sm_buffers = 0;
+
#ifdef SMARTALLOC
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
struct b_queue abq; /* Links on allocated queue */
unsigned ablen; /* Buffer length in bytes */
const char *abfname; /* File name pointer */
- sm_ushort ablineno; /* Line number of allocation */
+ sm_ushort ablineno; /* Line number of allocation */
};
static struct b_queue abqueue = { /* Allocated buffer queue */
&abqueue, &abqueue
};
+
static bool bufimode = false; /* Buffers not tracked when True */
#define HEAD_SIZE BALIGN(sizeof(struct abufhead))
nbytes += HEAD_SIZE + 1;
if ((buf = (char *)malloc(nbytes)) != NULL) {
+ struct abufhead *head = (struct abufhead *)buf;
P(mutex);
/* Enqueue buffer on allocated list */
qinsert(&abqueue, (struct b_queue *) buf);
- ((struct abufhead *) buf)->ablen = nbytes;
- ((struct abufhead *) buf)->abfname = bufimode ? NULL : fname;
- ((struct abufhead *) buf)->ablineno = (sm_ushort) lineno;
+ head->ablen = nbytes;
+ head->abfname = bufimode ? NULL : fname;
+ head->ablineno = (sm_ushort) lineno;
/* Emplace end-clobber detector at end of buffer */
buf[nbytes - 1] = (((long) buf) & 0xFF) ^ 0xC5;
buf += HEAD_SIZE; /* Increment to user data start */
+ if (++sm_buffers > sm_max_buffers) {
+ sm_max_buffers = sm_buffers;
+ }
+ sm_bytes += nbytes;
+ if (sm_bytes > sm_max_bytes) {
+ sm_max_bytes = sm_bytes;
+ }
V(mutex);
} else {
Emsg0(M_ABORT, 0, _("Out of memory\n"));
cp -= HEAD_SIZE;
qp = (struct b_queue *) cp;
+ struct abufhead *head = (struct abufhead *)cp;
P(mutex);
- Dmsg4(1150, "sm_free %d at %x from %s:%d\n",
- ((struct abufhead *)cp)->ablen, fp,
- ((struct abufhead *)cp)->abfname, ((struct abufhead *)cp)->ablineno);
+ Dmsg4(1150, "sm_free %d at %x from %s:%d\n",
+ head->ablen, fp,
+ head->abfname, head->ablineno);
/* The following assertions will catch virtually every release
of an address which isn't an allocated buffer. */
allocated space in the buffer by comparing the end of buffer
checksum with the address of the buffer. */
- if (((unsigned char *) cp)[((struct abufhead *) cp)->ablen - 1] !=
- ((((long) cp) & 0xFF) ^ 0xC5)) {
+ if (((unsigned char *)cp)[head->ablen - 1] != ((((long) cp) & 0xFF) ^ 0xC5)) {
V(mutex);
Emsg2(M_ABORT, 0, "Buffer overrun called from %s:%d\n", file, line);
}
-
+ sm_buffers--;
+ sm_bytes -= head->ablen;
qdchain(qp);
V(mutex);
attempts to access data through a pointer into storage that's
been previously released. */
- memset(cp, 0xAA, (int) ((struct abufhead *) cp)->ablen);
+ memset(cp, 0xAA, (int) head->ablen);
free(cp);
}
/* To catch sloppy code that assumes buffers obtained from
malloc() are zeroed, we preset the buffer contents to
- "designer garbage" consisting of alternating bits. */
+ "designer garbage" consisting of alternating bits. */
memset(buf, 0x55, (int) nbytes);
} else {
}
/* SM_REALLOC -- Adjust the size of a previously allocated buffer.
- Note that the trick of "resurrecting" a previously
+ Note that the trick of "resurrecting" a previously
freed buffer with realloc() is NOT supported by this
function. Further, because of the need to maintain
our control storage, SM_REALLOC must always allocate
return the buffer passed in. */
cp -= HEAD_SIZE;
- osize = ((struct abufhead *) cp)->ablen - (HEAD_SIZE + 1);
+ struct abufhead *head = (struct abufhead *)cp;
+ osize = head->ablen - (HEAD_SIZE + 1);
if (size == osize) {
return ptr;
}
return NULL from realloc() and leave the buffer in PTR
intact. */
+ sm_buffers--;
+ sm_bytes -= osize;
+
if ((buf = smalloc(fname, lineno, size)) != NULL) {
memcpy(buf, ptr, (int) sm_min(size, osize));
/* If the new buffer is larger than the old, fill the balance
- of it with "designer garbage". */
+ of it with "designer garbage". */
if (size > osize) {
memset(((char *) buf) + osize, 0x55, (int) (size - osize));
}
while (ap != (struct abufhead *) &abqueue) {
if ((ap == NULL) ||
- (ap->abq.qnext->qprev != (struct b_queue *) ap) ||
+ (ap->abq.qnext->qprev != (struct b_queue *) ap) ||
(ap->abq.qprev->qnext != (struct b_queue *) ap)) {
fprintf(stderr,
- "\nOrphaned buffers exist. Dump terminated following\n");
+ "\nOrphaned buffers exist. Dump terminated following\n");
fprintf(stderr,
- " discovery of bad links in chain of orphaned buffers.\n");
+ " discovery of bad links in chain of orphaned buffers.\n");
fprintf(stderr,
- " Buffer address with bad links: %lx\n", (long) ap);
+ " Buffer address with bad links: %lx\n", (long) ap);
break;
}
char errmsg[500];
bsnprintf(errmsg, sizeof(errmsg),
- "Orphaned buffer: %6u bytes allocated at line %d of %s %s\n",
+ "Orphaned buffer: %6u bytes allocated at line %d of %s %s\n",
memsize, ap->ablineno, my_name, ap->abfname
);
- fprintf(stderr, "%s", errmsg);
+ fprintf(stderr, "%s", errmsg);
if (bufdump) {
char buf[20];
unsigned llen = 0;
errmsg[0] = EOS;
while (memsize) {
if (llen >= 16) {
- bstrncat(errmsg, "\n", sizeof(errmsg));
+ bstrncat(errmsg, "\n", sizeof(errmsg));
llen = 0;
- fprintf(stderr, "%s", errmsg);
+ fprintf(stderr, "%s", errmsg);
errmsg[0] = EOS;
}
- bsnprintf(buf, sizeof(buf), " %02X",
+ bsnprintf(buf, sizeof(buf), " %02X",
(*cp++) & 0xFF);
bstrncat(errmsg, buf, sizeof(errmsg));
llen++;
memsize--;
}
- fprintf(stderr, "%s\n", errmsg);
+ fprintf(stderr, "%s\n", errmsg);
}
}
ap = (struct abufhead *) ap->abq.qnext;
void sm_check(const char *fname, int lineno, bool bufdump)
{
if (!sm_check_rtn(fname, lineno, bufdump)) {
- Emsg2(M_ABORT, 0, "Damaged buffer found. Called from %s:%d\n",
+ Emsg2(M_ABORT, 0, "Damaged buffer found. Called from %s:%d\n",
fname, lineno);
}
}
(ap->abq.qnext->qprev != (struct b_queue *) ap)) {
bad = 0x1;
}
- if (ap->abq.qprev->qnext != (struct b_queue *) ap) {
+ if (ap->abq.qprev->qnext != (struct b_queue *) ap) {
bad |= 0x2;
}
if (((unsigned char *) ap)[((struct abufhead *) ap)->ablen - 1] !=
badbuf |= bad;
if (bad) {
fprintf(stderr,
- "\nDamaged buffers found at %s:%d\n", fname, lineno);
+ "\nDamaged buffers found at %s:%d\n", fname, lineno);
if (bad & 0x1) {
- fprintf(stderr, " discovery of bad prev link.\n");
+ fprintf(stderr, " discovery of bad prev link.\n");
}
if (bad & 0x2) {
- fprintf(stderr, " discovery of bad next link.\n");
+ fprintf(stderr, " discovery of bad next link.\n");
}
if (bad & 0x4) {
- fprintf(stderr, " discovery of data overrun.\n");
+ fprintf(stderr, " discovery of data overrun.\n");
}
- fprintf(stderr, " Buffer address: %lx\n", (long) ap);
+ fprintf(stderr, " Buffer address: %lx\n", (long) ap);
if (ap->abfname != NULL) {
unsigned memsize = ap->ablen - (HEAD_SIZE + 1);
char errmsg[80];
fprintf(stderr,
- "Damaged buffer: %6u bytes allocated at line %d of %s %s\n",
+ "Damaged buffer: %6u bytes allocated at line %d of %s %s\n",
memsize, ap->ablineno, my_name, ap->abfname
);
if (bufdump) {
errmsg[0] = EOS;
while (memsize) {
if (llen >= 16) {
- strcat(errmsg, "\n");
+ strcat(errmsg, "\n");
llen = 0;
- fprintf(stderr, "%s", errmsg);
+ fprintf(stderr, "%s", errmsg);
errmsg[0] = EOS;
}
if (*cp < 0x20) {
- sprintf(errmsg + strlen(errmsg), " %02X",
+ sprintf(errmsg + strlen(errmsg), " %02X",
(*cp++) & 0xFF);
} else {
- sprintf(errmsg + strlen(errmsg), " %c ",
+ sprintf(errmsg + strlen(errmsg), " %c ",
(*cp++) & 0xFF);
}
llen++;
memsize--;
}
- fprintf(stderr, "%s\n", errmsg);
+ fprintf(stderr, "%s\n", errmsg);
}
}
}
bufimode = (bool) (mode != 0);
}
-/*
+/*
* Here we overload C++'s global new and delete operators
* so that the memory is allocated through smartalloc.
*/
+#ifdef xxx
void * operator new(size_t size)
{
// Dmsg1(000, "new called %d\n", size);
// Dmsg1(000, "free called 0x%x\n", buf);
sm_free(__FILE__, __LINE__, buf);
}
+#endif
#endif