📄 memcheck.c
字号:
} errno = ENOMEM; mem = NULL; }#endif } else { errno = ENOMEM; mem = NULL; } return mem;}static void memcheck_initialize(void){ const char *val; const char *env; memcheck_pagesize = getpagesize();#ifdef HAVE_SIGACTION# if defined(HAVE_SIGACTION_T_SA_SIGACTION) \ || defined(HAVE_STRUCT_SIGACTION_SA_SIGACTION) memcheck_act_segv[0].sa_sigaction = (sa_function)memcheck_sig; memcheck_act_bus[0].sa_sigaction = (sa_function)memcheck_sig;# elif defined(HAVE_SIGACTION_T_SA_HANDLER) \ || defined(HAVE_STRUCT_SIGACTION_SA_HANDLER) memcheck_act_segv[0].sa_handler = (sa_function)memcheck_sig; memcheck_act_bus[0].sa_handler = (sa_function)memcheck_sig;# endif memcheck_act_segv[0].sa_flags = SA_SIGINFO; memcheck_act_bus[0].sa_flags = SA_SIGINFO; if(!sigemptyset(&memcheck_act_segv[0].sa_mask)) { if(sigaction(SIGSEGV, &memcheck_act_segv[0], &memcheck_act_segv[1])) { memcheck_error("sigaction"); } if(sigaction(SIGBUS, &memcheck_act_bus[0], &memcheck_act_bus[1])) { memcheck_error("sigaction"); } }#endif if((env = getenv("MEMCHECK"))) { if(strstr(env, "under")) { memcheck_config.underruns = 1; } if((val = strstr(env, "restart"))) { if(!strcmp(val, "restart=r")) { memcheck_config.restart = PROT_READ; } if(!strcmp(val, "restart=w")) { memcheck_config.restart = PROT_READ | PROT_WRITE; } } if(strstr(env, "reuse")) { memcheck_config.reuse = 1; } if(strstr(env, "churn")) { memcheck_config.churn = 1; } if(strstr(env, "backtrace")) { memcheck_config.backtrace = 1; } if((val = strstr(env, "level="))) { if(val[6] == 'i') { memcheck_config.level = MEMCHECK_INFO; } if(val[6] == 'w') { memcheck_config.level = MEMCHECK_WARN; } if(val[6] == 'e') { memcheck_config.level = MEMCHECK_ERROR; } } if((val = strstr(env, "large="))) { memcheck_config.large = atoi(&val[6]); } if((val = strstr(env, "limit="))) { char *modifier; memcheck_config.limit = strtol(&val[6], &modifier, 10); if(modifier[0] == 'k' || modifier[0] == 'K') { memcheck_config.limit *= 1024; } if(modifier[0] == 'm' || modifier[0] == 'M') { memcheck_config.limit *= 1024 * 1024; } if(modifier[0] == 'g' || modifier[0] == 'G') { memcheck_config.limit *= 1024 * 1024 * 1024; } memcheck_config.limit /= memcheck_pagesize; } } if(atexit(memcheck_exit)) { memcheck_error("atexit"); }}static void memcheck_exit(void){ struct meminfo *mem; struct meminfo *next; for(mem = memcheck_head; mem != NULL; mem = next) { if(!memcheck_unprotect(mem)) { next = mem->next; memcheck_log(MEMCHECK_WARN, 0, "Never freed pointer %p of size %ld\n", mem->ptr, mem->size); memcheck_history(MEMCHECK_WARN, 0, mem); } else { break; } } if(memcheck_file >= 0) { close(memcheck_file); } if(memcheck_devzero >= 0) { if(close(memcheck_devzero)) { memcheck_error("close"); } } memcheck_devzero = -1; memcheck_file = -1;}static void memcheck_error(const char *s){#ifdef HAVE_PERROR perror(s);#else# ifdef HAVE_STRERROR fprintf(stderr, "%s: %s\n", s, strerror(errno));# else# ifdef HAVE_SYS_ERRLIST fprintf(stderr, "%s: %s\n", s, sys_errlist[errno]);# else# ifdef HAVE__SYS_ERRLIST fprintf(stderr, "%s: %s\n", s, _sys_errlist[errno]);# else fprintf(stderr, "%s: errno=%d\n", s, errno);# endif# endif# endif#endif}#ifdef HAVE_SIGACTION# if defined(HAVE_SIGACTION_T) || defined(HAVE_STRUCT_SIGACTION)static void memcheck_reraise(int signum, sa_action_type_arg2 arg2, void *context, void *address)# endif{ sigaction_t *act; act = NULL; if(signum == SIGSEGV) { act = &memcheck_act_segv[2 - memcheck_reentered_handler]; } if(signum == SIGBUS) { act = &memcheck_act_bus[2 - memcheck_reentered_handler]; } if(memcheck_reinstalled_handler != 0) { memcheck_reentered_handler = 1; } if((act->sa_handler == SIG_DFL || act->sa_handler == SIG_IGN) && !act->sa_flags && SA_SIGINFO) { sigaction(signum, act, NULL); } else {# if defined(HAVE_SIGACTION_T_SA_SIGACTION) \ || defined(HAVE_STRUCT_SIGACTION_SA_SIGACTION) ((void (*)(int, sa_action_type_arg2, void *, void *)) (act->sa_sigaction))(signum, arg2, context, address);# elif defined(HAVE_SIGACTION_T_SA_HANDLER) \ || defined(HAVE_STRUCT_SIGACTION_SA_HANDLER) (void)arg2; (void)context; (void)address; ((void (*)(int))(act->sa_handler))(signum);# endif }}static RETSIGTYPE memcheck_sig2(int signum, sa_action_type_arg2 arg2, void *context, void *address){ memcheck_reentered_handler = 0; memcheck_sig(signum, arg2, context, address);}static RETSIGTYPE memcheck_sig(int signum, sa_action_type_arg2 arg2, void *context, void *address){ static void *prev_text; static void *prev_data; int flags; void *new; int leave_handler; void *text; void *data; if(context != NULL) { text = context_text(context); data = context_data(context); } else { text = NULL; data = NULL; }# ifdef HAVE_SIGINFO_T if(arg2 != NULL && arg2 != (void *)-1) {# if !(defined(__linux__) \ || defined(_SCO_DS) \ || defined(__hpux) \ || defined(__arm) \ || defined(__arm__) \ || defined(__sparc__) \ || defined(__OpenBSD) \ || defined(__NetBSD) \ || defined(__FreeBSD__))# ifdef HAVE_SIGINFO_T_SI_ADDR if(text == NULL) { text = arg2->si_addr; }# endif# endif# if defined(_SCO_DS) \ || defined(__hppa) \ || defined(__hppa__) \ || defined(__ia64__) \ || defined(__s390__) \ || defined(__sparc__) \ || defined(__OpenBSD) \ || defined(__NetBSD) \ || defined(__FreeBSD__)# ifdef HAVE_SIGINFO_T_SI_ADDR if(data == NULL) { data = arg2->si_addr; }# endif# ifdef HAVE_SIGINFO_T_SI_PTR if(data == NULL) { data = arg2->si_ptr; }# endif# endif }# else if(data == NULL) { data = (void *)arg2; }# endif leave_handler = 0; if(memcheck_reentered_handler == 0) { memcheck_log(MEMCHECK_ERROR, 1, "%srun of %p at %p\n", memcheck_config.underruns ? "Under" : "Over", data, text); if(memcheck_config.backtrace) { memcheck_get_symbols(MEMCHECK_ERROR, 1, memcheck_get_backtrace(2 + memcheck_reinstalled_handler)); } if(memcheck_config.restart && data != NULL) { if(prev_text != text || prev_data != data) { prev_text = text; prev_data = data; if(mprotect((void *)(((long)(data)) & -memcheck_pagesize), memcheck_pagesize, memcheck_config.restart)) { flags = MAP_PRIVATE;# ifdef MAP_ANONYMOUS flags |= MAP_ANONYMOUS;# endif if((new = mmap((void *)(((long)(data)) & -memcheck_pagesize), memcheck_pagesize, PROT_READ | PROT_WRITE, flags, memcheck_devzero, 0)) != MAP_FAILED && new == (void *)(((long)(data)) & -memcheck_pagesize)) { memset(new, 0xa5, memcheck_pagesize); leave_handler = 1; } } else { leave_handler = 1; } } } } if(leave_handler == 0) { memcheck_reraise(signum, arg2, context, address); } else { if(memcheck_reinstalled_handler != 0) { memcheck_reentered_handler = 1; } }}#endif#ifndef __GNUC__static void *memcheck_get_return_address(void *stack){ /* Dig a return address off of the stack. */ return (void *)*((long *)(((char *)stack) + ((STACK_DIRECTION) * STACK_OFFSET * sizeof(void *))));}#endifstatic const struct backtrace *memcheck_get_backtrace(int skip_frames){ struct backtrace *retval;#ifdef HAVE_BACKTRACE /* Support a single recursion of malloc for implementations * of atexit that need to call that function. */ static struct backtrace bt[2]; static int sw = 0; if((bt[sw].size = backtrace(bt[sw].array, BACKTRACE_SIZE)) > skip_frames) { bt[sw].size -= skip_frames; memmove(&bt[sw].array[0], &bt[sw].array[skip_frames], bt[sw].size * sizeof(bt[0].array[0])); retval = &bt[sw]; sw = !sw; } else#else (void)skip_frames;#endif { retval = NULL; } return retval;}static void memcheck_get_symbols(int level, int flush, const struct backtrace *addr){#ifdef HAVE_BACKTRACE if(level <= memcheck_config.level && addr != NULL && addr->size != 0) { if(write(memcheck_file, "------------------------------------------------------------\n", 61) < 0) { memcheck_error("write"); } backtrace_symbols_fd(addr->array, addr->size, memcheck_file); if(write(memcheck_file, "============================================================\n", 61) < 0) { memcheck_error("write"); } if(flush) {#ifdef HAVE_FSYNC if(fsync(memcheck_file) < 0) { memcheck_error("fsync"); }#endif } } else#endif { (void)level; (void)addr; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -