int comparator(const void* ap, const void* bp) { getStackTrace(goldenFrames); int a = *static_cast<const int*>(ap); int b = *static_cast<const int*>(bp); return a < b ? -1 : a > b ? 1 : 0; }
void jniLogException(C_JNIEnv* env, int priority, const char* tag, jthrowable exception) { JNIEnv* e = reinterpret_cast<JNIEnv*>(env); scoped_local_ref<jthrowable> currentException(env, (*env)->ExceptionOccurred(e)); if (exception == NULL) { exception = currentException.get(); if (exception == NULL) { return; } } if (currentException.get() != NULL) { (*env)->ExceptionClear(e); } char* buffer = getStackTrace(env, exception); if (buffer == NULL) { (*env)->ExceptionClear(e); buffer = getExceptionSummary(env, exception); } __android_log_write(priority, tag, buffer); free(buffer); if (currentException.get() != NULL) { (*env)->Throw(e, currentException.get()); // rethrow } }
std::string gdbmiStack(CIDebugControl *debugControl, CIDebugSymbols *debugSymbols, unsigned maxFrames, bool humanReadable, std::string *errorMessage) { bool incomplete; const StackFrames frames = getStackTrace(debugControl, debugSymbols, maxFrames, &incomplete, errorMessage); if (frames.empty() && maxFrames > 0) return std::string(); std::ostringstream str; str << '['; const StackFrames::size_type size = frames.size(); for (StackFrames::size_type i = 0; i < size; ++i) { if (i) str << ','; frames.at(i).formatGDBMI(str, (int)i); if (humanReadable) str << '\n'; } if (incomplete) // Empty elements indicates incomplete. str <<",{}"; str << ']'; return str.str(); }
extern "C" std::string jniGetStackTrace(C_JNIEnv* env, jthrowable exception) { JNIEnv* e = reinterpret_cast<JNIEnv*>(env); scoped_local_ref<jthrowable> currentException(env, (*env)->ExceptionOccurred(e)); if (exception == NULL) { exception = currentException.get(); if (exception == NULL) { return "<no pending exception>"; } } if (currentException.get() != NULL) { (*env)->ExceptionClear(e); } std::string trace; if (!getStackTrace(env, exception, trace)) { (*env)->ExceptionClear(e); getExceptionSummary(env, exception, trace); } if (currentException.get() != NULL) { (*env)->Throw(e, currentException.get()); // rethrow } return trace; }
void MemoryProfile::logAllocationImpl(void *ptr, size_t size) { TRACE(3, "logging allocation at %p of %lu bytes\n", ptr, size); ProfileStackTrace trace = getStackTrace(); Allocation alloc { size, trace }; m_livePointers[ptr] = alloc; m_dump.addAlloc(size, trace); }
inline void sendStackTrace(MPI_Comm globalComm) { // std::string stringToSend(testStringValue); std::string stringToSend(getStackTrace()); int lengthOfString = stringToSend.length(); lengthOfString += oneForNullTerminator; MPI_Send(&lengthOfString, 1, MPI_INT, getDestinationProc(globalComm), STRING_SIZE_TAG, globalComm); MPI_Send(const_cast<char*>(stringToSend.c_str()), lengthOfString, MPI_CHAR, getDestinationProc(globalComm), STRING_TAG, globalComm); }
void __checked_pointer_table::__stderr_reporter::report(const void* address, size_t size, const char* /*filename*/, int /* line */ ) { printf(CHKPTR_PREFIX "Leaked %lu bytes at address %p\n", (unsigned long)size, address); printf(getStackTrace(true, CHKPTR_STACK_WINDOW_SIZE, (CxxTest::StackElem*)(((char*)address) + size), CHKPTR_STACK_TRACE_INITIAL_PREFIX, CHKPTR_STACK_TRACE_OTHER_PREFIX).c_str()); printf(CHKPTR_PREFIX "\n"); }
std::ostream& StackTraceUtils::getStackTrace(std::ostream &stream) { LocaleUtils::CLocaleScope localeScope(stream); char8_t buf[512]; detail::LocalString str(buf, sizeof(buf)); detail::StackTraceStringHandler handler(str); getStackTrace(handler); stream << str.tryGet(); return stream; }
/** * @brief ToString * 获得详细错误信息 * @return {string} */ const string& baseException::ToString() const { if (_mWhat.empty()) { stringstream sstr(""); if (mLine_ > 0) { sstr<<mFile_<<"("<<mLine_<<")"; } sstr<<": "<<getClassName(); if (!getMessage().empty()) { sstr<<": "<<getMessage(); } sstr<<"\nStack Trace:\n"; sstr<<getStackTrace(); _mWhat = sstr.str(); return _mWhat; } }
FinalReportGenerator::~FinalReportGenerator() { // Have to use C-style output, since the // standard C++ objects have already been finalized! bool First = true; reportGenerated = true; InternalCall = true; // Turn off reporting #ifdef MW_XML_OUTPUT_FILE FILE* xmlFile = fopen(MW_XML_OUTPUT_FILE, "w"); fprintf( xmlFile, "<?xml version='1.0'?>\n"); fprintf( xmlFile, "<memwatch>\n"); #endif // Search the database for ( int i = 0; i < MaxUsed; i++ ) { if ( DB[i].Address ) { // We found an orphan block. if ( First ) { // At least, we think we did. The text explains all. #ifndef MW_XML_OUTPUT_FILE fprintf( OUTFILE, "\n" MW_PREFIX "******************* LEAKS *******************\n" MW_PREFIX "Possible memory leaks detected.\n" // MW_PREFIX //" A small number of these leaks" // "may be due to standard library code.\n" MW_PREFIX "The identified leaks:\n" MW_PREFIX "\n" ); #endif First = false; } // Write out everything we know about the bad block. // If you put a breakpoint here and a watch on // DB[i].From you can use the CPU window to find // the exact statement. (Right click, Go To) #ifdef MW_XML_OUTPUT_FILE fprintf( xmlFile, " <leak " "address=\"%p\" size=\"%lu\" %s>\n", DB[i].Address, (unsigned long)DB[i].Size, (DB[i].isArray ? "array=\"yes\"" : "")); #else fprintf( OUTFILE, // "\n******************* ERROR *******************\n" MW_PREFIX "Memory block at %p not deleted (", DB[i].Address ); if ( DB[i].isArray ) fprintf( OUTFILE, "array " ); fprintf( OUTFILE, "%lu byte(s) long", (unsigned long)DB[i].Size ); //if ( DB[i].Size > 500 ) fprintf( OUTFILE, "--possible STL leak?" ); fprintf( OUTFILE, ").\n" ); #endif #ifdef CXXTEST_TRACE_STACK fprintf( #ifdef MW_XML_OUTPUT_FILE xmlFile, #else OUTFILE, #endif getStackTrace( MW_STACK_WINDOW_SIZE, (CxxTest::StackElem*)( ((char*)DB[i].Address) + DB[i].Size + hiSafetySize ), MW_STACK_TRACE_INITIAL_PREFIX ).c_str() ); #endif #ifdef MW_XML_OUTPUT_FILE fprintf( xmlFile, " </leak>\n" ); #endif } } #ifdef MW_XML_OUTPUT_FILE fprintf( xmlFile, " <summary " "max-blocks=\"%d\" " "calls-to-new=\"%d\" " "calls-to-delete=\"%d\" " "calls-to-new-array=\"%d\" " "calls-to-delete-array=\"%d\" " #ifdef REPORT_NULLS "calls-to-delete-null=\"%d\" " #endif "/>\n", (MaxUsed + 1), NumNewNonArray, NumNonArrayDeletes, NumNewArray, NumArrayDeletes #ifdef REPORT_NULLS ,NumNullDeletes #endif ); #else fprintf( OUTFILE, "\n**************** SUMMARY ****************\n" "Max blocks in use: %d\n" "Calls to new: %d\n" "Calls to delete (non-NULL): %d\n" "Calls to new[]: %d\n" "Calls to delete[] (non-NULL): %d\n", (MaxUsed + 1), NumNewNonArray, NumNonArrayDeletes, NumNewArray, NumArrayDeletes ); #ifdef REPORT_NULLS fprintf( OUTFILE, "Calls to delete (NULL): %d\n", NumNullDeletes ); #endif #endif #ifdef MW_XML_OUTPUT_FILE fprintf( xmlFile, "</memwatch>\n"); fclose( xmlFile ); #endif InternalCall = false; }
void *malloc(size_t size) { ulong *begin; sMemArea *area,*prev,*narea; if(size == 0) return NULL; usemdown(&heapSem); /* align and we need 3 ulongs for the guards */ size = ROUND_UP(size,sizeof(ulong)) + sizeof(ulong) * 4; /* find a suitable area */ prev = NULL; area = usableList; while(area != NULL) { if(area->size >= size) break; prev = area; area = area->next; } /* no area found? */ if(area == NULL) { if(!loadNewSpace(size)) { usemup(&heapSem); return NULL; } /* we can assume that it fits */ area = usableList; /* remove from usable-list */ usableList = area->next; } else { /* remove from usable-list */ if(prev == NULL) usableList = area->next; else prev->next = area->next; } /* is there space left? */ if(size < area->size) { if(freeList == NULL) { if(!loadNewAreas()) { /* TODO we may have changed something... */ usemup(&heapSem); return NULL; } } /* split the area */ narea = freeList; freeList = freeList->next; narea->address = (void*)((uintptr_t)area->address + size); narea->size = area->size - size; area->size = size; /* insert in usable-list */ narea->next = usableList; usableList = narea; } #if DEBUG_ALLOC_N_FREE if(DEBUG_ALLOC_N_FREE_PID == -1 || getpid() == DEBUG_ALLOC_N_FREE_PID) { size_t i = 0; uintptr_t *trace = getStackTrace(); debugf("[A] %x %d ",(char*)area->address + 3,area->size); while(*trace && i++ < 10) { debugf("%x",*trace); if(trace[1]) debugf(" "); trace++; } debugf("\n"); } #endif /* add guards */ begin = (ulong*)area->address; begin[0] = (ulong)area; begin[1] = size - sizeof(ulong) * 4; begin[2] = GUARD_MAGIC; begin[size / sizeof(ulong) - 1] = GUARD_MAGIC; usemup(&heapSem); return begin + 3; }
void free(void *addr) { ulong *begin; sMemArea *area,*a,*prev,*next,*nprev,*pprev,*tprev; /* addr may be null */ if(addr == NULL) return; /* check guards */ begin = (ulong*)addr - 3; area = (sMemArea*)begin[0]; vassert(begin[0] != FREE_MAGIC,"Duplicate free of %p?",addr); assert(begin[2] == GUARD_MAGIC); assert(begin[begin[1] / sizeof(ulong) + 3] == GUARD_MAGIC); usemdown(&heapSem); /* mark as free */ begin[0] = FREE_MAGIC; /* find the previous and next free areas */ prev = NULL; next = NULL; tprev = NULL; pprev = NULL; nprev = NULL; a = usableList; while(a != NULL) { if((uintptr_t)a->address + a->size == (uintptr_t)begin) { prev = a; pprev = tprev; } if((uintptr_t)a->address == (uintptr_t)begin + area->size) { next = a; nprev = tprev; } /* do we have both? */ if(prev && next) break; tprev = a; a = a->next; } #if DEBUG_ALLOC_N_FREE if(DEBUG_ALLOC_N_FREE_PID == -1 || getpid() == DEBUG_ALLOC_N_FREE_PID) { size_t i = 0; uintptr_t *trace = getStackTrace(); debugf("[F] %x %d ",addr,area->size); while(*trace && i++ < 10) { debugf("%x",*trace); if(trace[1]) debugf(" "); trace++; } debugf("\n"); } #endif /* see what we have to merge */ if(prev && next) { /* merge prev & area & next */ area->size += prev->size + next->size; area->address = prev->address; /* remove prev and next from the list */ if(nprev) nprev->next = next->next; else usableList = next->next; /* special-case if next is the previous of prev */ if(pprev == next) { if(nprev) nprev->next = prev->next; else usableList = prev->next; } else { if(pprev) pprev->next = prev->next; else usableList = prev->next; } /* put area on the usable-list */ area->next = usableList; usableList = area; /* put prev and next on the freelist */ prev->next = next; next->next = freeList; freeList = prev; } else if(prev) { /* merge preg & area */ prev->size += area->size; /* put area on the freelist */ area->next = freeList; freeList = area; } else if(next) { /* merge area & next */ next->address = area->address; next->size += area->size; /* put area on the freelist */ area->next = freeList; freeList = area; } else { /* insert area in usableList */ area->next = usableList; usableList = area; } usemup(&heapSem); }