📄 memcheck.c
字号:
void *ptr; ptr = memcheck_allocator(file, line, calloc_function, addr, trace, NULL, size * n); if(ptr != NULL && n * size != 0) { memset(ptr, 0, n * size); } return ptr;}static void *memcheck_realloc_internal(const char *file, int line, const void *addr, const struct backtrace *trace, void *ptr, size_t size){ return memcheck_allocator(file, line, realloc_function, addr, trace, ptr, size);}static void memcheck_free_internal(const char *file, int line, const void *addr, const struct backtrace *trace, const void *ptr){ memcheck_allocator(file, line, free_function, addr, trace, ptr, 0);}static void memcheck_cfree_internal(const char *file, int line, const void *addr, const struct backtrace *trace, const void *ptr){ memcheck_allocator(file, line, cfree_function, addr, trace, ptr, 0);}static void *memcheck_valloc_internal(const char *file, int line, const void *addr, const struct backtrace *trace, size_t size){ return memcheck_allocator(file, line, valloc_function, addr, trace, NULL, size);}static void *memcheck_memalign_internal(const char *file, int line, const void *addr, const struct backtrace *trace, size_t boundary, size_t size){ (void)boundary; return memcheck_allocator(file, line, memalign_function, addr, trace, NULL, size);}static int memcheck_posix_memalign_internal(const char *file, int line, const void *addr, const struct backtrace *trace, void **memptr, size_t alignment, size_t size){ int retval; void *ptr; if((alignment % sizeof(void *)) == 0 && (size & (size - 1)) == 0) { if((ptr = memcheck_memalign_internal(file, line, addr, trace, alignment, size)) != NULL) { *memptr = ptr; retval = 0; } else { retval = errno; } } else { retval = EINVAL; } return retval;}static void *memcheck_allocator(const char *file, int line, int func, const void *addr, const struct backtrace *trace, const void *ptr, size_t nsize){#ifdef HAVE_SIGACTION sigaction_t act;#endif struct caller caller; struct meminfo *omem; struct meminfo *nmem; size_t opages; size_t npages; size_t upages; size_t osize; size_t ocount; void *optr; void *nptr; int logged; int history; logged = MEMCHECK_NONE; history = MEMCHECK_NONE; /* Initialize, if first time. */ if(memcheck_pagesize == 0) { memcheck_initialize(); }#ifdef HAVE_SIGACTION else { if(!sigaction(SIGSEGV, NULL, &act)) {# if defined(HAVE_SIGACTION_T_SA_SIGACTION) \ || defined(HAVE_STRUCT_SIGACTION_SA_SIGACTION) if(act.sa_sigaction != memcheck_act_segv[0].sa_sigaction) { memcheck_act_segv[0].sa_sigaction = (sa_function)memcheck_sig2;# elif defined(HAVE_SIGACTION_T_SA_HANDLER) \ || defined(HAVE_STRUCT_SIGACTION_SA_HANDLER) if(act.sa_handler != memcheck_act_segv[0].sa_handler) { memcheck_act_segv[0].sa_handler = (sa_function)memcheck_sig2;# endif /* Somebody removed our segv hander, put it back. */ if(memcheck_act_segv[2].sa_handler == NULL) { if(sigaction(SIGSEGV, &memcheck_act_segv[0], &memcheck_act_segv[2])) { memcheck_error("sigaction"); } } memcheck_reinstalled_handler = 1; } } else { memcheck_error("sigaction"); } if(!sigaction(SIGBUS, NULL, &act)) {# if defined(HAVE_SIGACTION_T_SA_SIGACTION) \ || defined(HAVE_STRUCT_SIGACTION_SA_SIGACTION) if(act.sa_sigaction != memcheck_act_bus[0].sa_sigaction) { memcheck_act_bus[0].sa_sigaction = (sa_function)memcheck_sig2;# elif defined(HAVE_SIGACTION_T_SA_HANDLER) \ || defined(HAVE_STRUCT_SIGACTION_SA_HANDLER) if(act.sa_handler != memcheck_act_bus[0].sa_handler) { memcheck_act_bus[0].sa_handler = (sa_function)memcheck_sig2;# endif /* Somebody removed our bus hander, put it back. */ if(memcheck_act_bus[2].sa_handler == NULL) { if(sigaction(SIGBUS, &memcheck_act_bus[0], &memcheck_act_bus[2])) { memcheck_error("sigaction"); } } memcheck_reinstalled_handler = 1; } } else { memcheck_error("sigaction"); } }#endif#ifdef HAVE_BACKTRACE if(trace != NULL) { memcpy(&caller.trace, trace, sizeof(caller.trace)); } else { (void)trace; memset(&caller.trace, 0, sizeof(caller.trace)); }#else (void)trace;#endif caller.addr = addr; caller.file = file; caller.line = line; caller.func = func; /* Check for NULL pointer on deallocations. */ if(ptr == NULL && memcheck_functions[func].type & free_type) { memcheck_log_info(MEMCHECK_INFO, 1, "NULL", ptr, &caller); logged = logged > MEMCHECK_INFO ? logged : MEMCHECK_INFO; } if(memcheck_functions[func].type & alloc_type) { /* Check for zero size on allocations. */ if(nsize == 0) { memcheck_log_info(MEMCHECK_INFO, 1, "Zero size", ptr, &caller); logged = logged > MEMCHECK_INFO ? logged : MEMCHECK_INFO; } else if(nsize >= memcheck_config.large && memcheck_config.large > 0) { memcheck_log_info(MEMCHECK_INFO, 1, "Large allocation", ptr, &caller); logged = logged > MEMCHECK_INFO ? logged : MEMCHECK_INFO; } } /* Retrieve info for old allocation. */ if(ptr != NULL && memcheck_functions[func].type & free_type) { omem = meminfo_from_ptr(ptr); if(!memcheck_unprotect(omem)) { if(memcheck_check_sentry(omem)) { memcheck_log_info(MEMCHECK_ERROR, 1, memcheck_config.underruns ? "Detected overrun" : "Detected underrun", ptr, &caller); history = history > MEMCHECK_ERROR ? history : MEMCHECK_ERROR; logged = logged > MEMCHECK_ERROR ? logged : MEMCHECK_ERROR; } optr = omem->ptr; if(optr != ptr) { memcheck_log_info(MEMCHECK_ERROR, 1, "Invalid", ptr, &caller); logged = logged > MEMCHECK_ERROR ? logged : MEMCHECK_ERROR; } osize = omem->size; opages = omem->pages; ocount = omem->count; /* Check for old allocation already freed. */ if(!omem->inuse) { memcheck_log_info(MEMCHECK_ERROR, 1, "Already freed", ptr, &caller); history = history > MEMCHECK_ERROR ? history : MEMCHECK_ERROR; logged = logged > MEMCHECK_ERROR ? logged : MEMCHECK_ERROR; } } else { omem = NULL; optr = NULL; osize = 0; opages = 0; ocount = 0; memcheck_log_info(MEMCHECK_ERROR, 1, "Invalid", ptr, &caller); logged = logged > MEMCHECK_ERROR ? logged : MEMCHECK_ERROR; } } else { omem = NULL; optr = NULL; osize = 0; opages = 0; ocount = 0; } /* Calculate number of pages for new allocation. */ if(memcheck_functions[func].type & alloc_type) { /* Always need an info page. */ npages = 1; if(nsize > 0) { npages += memcheck_user_pages(nsize); } if(ocount >= MAX_REALLOC_CALL) { npages += 1 + ((ocount - MAX_REALLOC_CALL + 1) * sizeof(struct caller)) / memcheck_pagesize; } if(opages == npages && !memcheck_config.churn) /* If page count isn't changing and we aren't "churning". */ { nmem = omem; if(osize == nsize) /* If byte count isn't changing, return the original pointer. */ { nptr = optr; } else /* Relocate the pointer on the same page. */ { memcheck_update(nmem, &caller); memcheck_setup(nmem, npages, nsize); nptr = nmem->ptr; } } else /* The page count _is_ changing or we _are_ "churning". */ { if((nmem = memcheck_get(npages)) != NULL) /* Got a new block of memory. */ { if(omem != NULL) { /* Continue tracking, even if the actual data moves. */ memcpy(nmem, omem, memcheck_pagesize); if(ocount >= MAX_REALLOC_CALL) { upages = memcheck_user_pages(nsize); /* Set the realloc overflow area after the end of the user area. */ nmem->realloc2 = (struct caller *)((char *)nmem + memcheck_pagesize * (1 + upages)); if(ocount > MAX_REALLOC_CALL) { /* Continue tracking the realloc overflow area as well. */ memcpy(nmem->realloc2, omem->realloc2, (ocount - MAX_REALLOC_CALL) * sizeof(struct caller)); } } memcheck_update(nmem, &caller); } else { memcheck_insert(nmem, &caller); } memcheck_setup(nmem, npages, nsize); nptr = nmem->ptr; } else /* New block failed. */ { memcheck_log_info(MEMCHECK_ERROR, 1, "Out of memory", ptr, &caller); logged = logged > MEMCHECK_ERROR ? logged : MEMCHECK_ERROR; nptr = NULL; } } } else { nmem = NULL; nptr = NULL; nsize = 0; npages = 0; } if(logged) { if(memcheck_config.backtrace) { memcheck_get_symbols(logged, 1, trace); } if(history) { memcheck_history(history, 1, omem); } } /* Old and new block both have size and new pointer exists. */ if(osize > 0 && nsize > 0 && nptr != NULL && optr != nptr) { memmove(nptr, optr, osize > nsize ? nsize : osize); } /* Old block exists and isn't being retained. */ if(omem != NULL && omem != nmem && omem->inuse) { memcheck_delete(omem, &caller); memcheck_put(omem); } if(nmem != NULL) { memcheck_place_sentry(nmem); memcheck_protect(nmem, PROT_READ | PROT_WRITE); } return nptr;}static int memcheck_check_sentry(struct meminfo *mem){ long sentry; int retval; if(mem->sentry != NULL) { /* Use memcpy instead of cast+assignment * * due to possible mis-alignment. */ memcpy(&sentry, mem->sentry, sizeof(sentry)); if(sentry != memcheck_sentry) { retval = 1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -