11 #include <dispatch/dispatch.h>
13 #include <sys/errno.h>
31 fprintf(stderr,
"%s\n", message);
43 void *compositionState = NULL;
53 #ifdef VUOHEAP_TRACEALL
57 static bool VuoHeap_isComposition(
void)
59 static bool isComposition =
false;
60 static dispatch_once_t once = 0;
61 dispatch_once(&once, ^{
62 isComposition = dlsym(RTLD_DEFAULT,
"vuoCompositionStateKey");
96 for (
int i = 0; i < 10000; ++i)
109 __sync_synchronize();
128 if ((
unsigned long)pointer & 0xf)
135 if ((
unsigned long)pointer < 0x100000000)
142 if ((
unsigned long)pointer > 0xffffffffffff)
158 int pageSize = getpagesize();
159 long heapPageMask = ~((long)pageSize-1);
160 long heapPage = (long)pointer & heapPageMask;
163 mlock((
void *)heapPage, pageSize);
164 munlock((
void *)heapPage, pageSize);
168 if (mincore((
void *)heapPage, pageSize, pageStatus) == 0)
169 return pageStatus[0] & MINCORE_INCORE;
184 char *pointerAsChar = (
char *)pointer;
185 for (
int i = 0; i < 16; ++i)
186 if (isprint(pointerAsChar[i]))
187 summary[i] = pointerAsChar[i];
193 strlcpy(summary,
"(not allocated)", 17);
205 const char *format =
"%s:%d :: %s() :: %s";
206 int size = snprintf(NULL, 0, format, e.file, e.line, e.function, e.variable);
207 char *description = (
char *)malloc(size+1);
208 snprintf(description, size+1, format, e.file, e.line, e.function, e.variable);
231 const double dumpInterval = 5.0;
232 dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, DISPATCH_TIMER_STRICT, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
233 dispatch_source_set_timer(timer, dispatch_walltime(NULL,0), NSEC_PER_SEC*dumpInterval, NSEC_PER_SEC*dumpInterval);
234 dispatch_source_set_event_handler(timer, ^{
235 fprintf(stderr,
"\n\n\n\n\nreferenceCounts:\n");
239 const void *heapPointer = i->first;
240 char pointerSummary[17];
243 fprintf(stderr,
"\t% 3d refs to %p \"%s\", registered at %s\n", i->second.referenceCount, heapPointer, pointerSummary, description);
248 dispatch_resume(timer);
264 ostringstream errorMessage;
266 <<
", VuoRelease was not called enough times for:" << endl;
269 const void *heapPointer = i->first;
270 char pointerSummary[17];
273 errorMessage <<
"\t" << setw(3) << i->second.referenceCount <<
" refs to " << heapPointer <<
" \"" << pointerSummary <<
"\", registered at " << description << endl;
305 ostringstream errorMessage;
308 <<
", VuoRegister was called for bogus pointer " << heapPointer
309 <<
" " << description;
314 bool isAlreadyReferenceCounted;
323 #ifdef VUOHEAP_TRACEALL
324 if (VuoHeap_isComposition())
329 fprintf(stderr,
"table=%p VuoRegister(%p) %s\n",
referenceCounts, heapPointer, pointerName);
334 map<const void *, VuoHeapEntry>::iterator i =
referenceCounts->find(heapPointer);
336 if (! isAlreadyReferenceCounted)
339 (*referenceCounts)[heapPointer] = (
VuoHeapEntry){updatedCount, deallocate, file, linenumber, func, pointerName};
342 updatedCount = i->second.referenceCount;
347 if (isAlreadyReferenceCounted)
349 ostringstream errorMessage;
352 <<
", VuoRegister was called more than once for " << heapPointer
353 <<
" " << description;
365 int VuoRegisterSingletonF(
const void *heapPointer,
const char *file,
unsigned int linenumber,
const char *func,
const char *pointerName)
372 ostringstream errorMessage;
375 <<
", VuoRegisterSingleton was called for bogus pointer " << heapPointer
376 <<
" " << description;
381 bool isAlreadyReferenceCounted;
389 #ifdef VUOHEAP_TRACEALL
390 if (VuoHeap_isComposition())
395 fprintf(stderr,
"table=%p VuoRegisterSingleton(%p) %s\n",
referenceCounts, heapPointer, pointerName);
406 if (! isAlreadyReferenceCounted)
411 if (isAlreadyReferenceCounted)
413 ostringstream errorMessage;
416 <<
", VuoRegisterSingleton was called more than once for " << heapPointer
417 <<
" " << description;
422 return isAlreadyReferenceCounted ? 1 : 0;
433 extern "C" int VuoRetainF(
const void *heapPointer,
const char *file,
unsigned int linenumber,
const char *func)
452 char pointerSummary[17];
454 ostringstream errorMessage;
456 <<
", VuoRetain was called for bogus pointer " << heapPointer
457 <<
" \"" << pointerSummary <<
"\"";
461 int updatedCount = -1;
462 bool foundSingleton =
false;
469 map<const void *, VuoHeapEntry>::iterator i =
referenceCounts->find(heapPointer);
472 #ifdef VUOHEAP_TRACEALL
473 if (VuoHeap_isComposition())
484 updatedCount = ++(i->second.referenceCount);
492 if (updatedCount == -1 && !foundSingleton)
494 char pointerSummary[17];
496 ostringstream errorMessage;
498 <<
", VuoRetain was called for unregistered pointer " << heapPointer
499 <<
" \"" << pointerSummary <<
"\"";
514 extern "C" int VuoReleaseF(
const void *heapPointer,
const char *file,
unsigned int linenumber,
const char *func)
534 char pointerSummary[17];
536 ostringstream errorMessage;
538 <<
", VuoRelease was called for bogus pointer " << heapPointer
539 <<
" \"" << pointerSummary <<
"\"";
543 int updatedCount = -1;
544 bool foundSingleton =
false;
545 bool isRegisteredWithoutRetain =
false;
552 map<const void *, VuoHeapEntry>::iterator i =
referenceCounts->find(heapPointer);
555 #ifdef VUOHEAP_TRACEALL
556 if (VuoHeap_isComposition())
568 if (i->second.referenceCount == 0)
570 isRegisteredWithoutRetain =
true;
574 updatedCount = --(i->second.referenceCount);
576 if (updatedCount == 0)
578 deallocate = i->second.deallocateFunction;
589 if (updatedCount == 0)
592 #ifdef VUOHEAP_TRACEALL
593 if (VuoHeap_isComposition())
606 fprintf(stderr,
"table=%p VuoDeallocate(%p)\n",
referenceCounts, heapPointer);
611 deallocate((
void *)heapPointer);
613 else if (updatedCount == -1 && !foundSingleton)
615 char pointerSummary[17];
617 ostringstream errorMessage;
619 <<
", VuoRelease was called for "
620 << (isRegisteredWithoutRetain ?
"unretained" :
"unregistered")
621 <<
" pointer " << heapPointer
622 <<
" \"" << pointerSummary <<
"\"";
638 map<const void *, VuoHeapEntry>::iterator i =
referenceCounts->find(heapPointer);
642 return strdup(
"(pointer was not VuoRegister()ed)");