⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 yamd.c

📁 很好用的内存泄漏检测工具。要配合linux的gcc使用,安装后将你的编译器gcc命令换成yamd-gcc就行了
💻 C
📖 第 1 页 / 共 4 页
字号:
    {      log_detail(level, "Seems not to be associated with any block.\n");    }}void__yamd_describe_address(void *a){  /* HACK HACK HACK */  /* This is intended for debuggers, so make it show up. */  int ofd;  int oll;  log_flush();  ofd = log_fd;  log_fd = 2; /* stderr */  oll = min_log_level;  min_log_level = 0;  describe_address(LOG_INFO, (addr)a);  log_flush();  log_fd = ofd;  min_log_level = oll;}/* Hmm.  This is probably not overly safe; we call printf and such   from within a signal handler.  If the crash was inside a stdio function,   its state might be funny and things could get very screwed up. */static void disclaimer(void){  static char message[] = "This appears to be a non-malloc bug, dumping core\n";  write(2, message, sizeof(message));  signal(SIGSEGV, SIG_DFL);  return;}#ifdef __linux__#ifdef __i386__static void sigsegv_handler(int signum, struct sigcontext ctx){  (void)signum; /* shut the compiler up */  /* Find out if this is a fault we're trying to catch */  if (ctx.trapno != 14  /* Not a page fault */      || !(ctx.err & 4)) /* Not a user access */    {      disclaimer();      return;    }  /* Note that using cr2 here assumes that the base of DS is 0.     Thank God for systems with real memory mapping... */  handle_page_fault(ctx.cr2, ctx.err & 2, ctx.eip, ctx.ebp);  return;  /* Resume the faulting instruction; it may or may not have	      been fixed up */}#endif#endif#ifdef DJGPP_SIGNAL/* Curses.  None of this clever hackish stuff works, since CWSDPMI   zeroes out cr2 for its own purposes.  Getting the faulting cr2 is   probably going to require hacking of CWSDPMI itself, or writing a   newer-style exception handler (only for DPMI 1.0 and not supported   by CWSDPMI).  So at present, let's just leave this stuff out and   let the debuggers handle it. */static intget_ring(void){  unsigned long desc[2];  if (__dpmi_get_descriptor(_my_cs(), desc) < 0)    return -1;  /* DPL is bits 13 and 14 of upper word */  return (desc[1] >> 13) & 0x2;}static voidsigsegv_handler(int sig){  unsigned long cr2;  unsigned long err_code;  (void)sig; /* shut the compiler up */#ifdef DEBUG  printf("In signal handler\n");#endif  /* Misnamed; member `signum' is really the exception number.  14 ==     page fault. */  if (__djgpp_exception_state->__signum != 14)    {#ifdef DEBUG      printf("Bad exception number %ld\n", __djgpp_exception_state->__signum);#endif       disclaimer();      return;    }  if (get_ring() != 0)    return; /* without cr2 we can't do much */  asm("movl %%cr2, %0" : "=r" (cr2));  /* Undocumented feature.  From dpmiexcp.c-- MAY CHANGE! */  err_code = __djgpp_exception_state->__sigmask & 0xffff;  /* cr2 is linear address, so we must adjust. */#ifdef DEBUG  printf("cr2 = %#08lx\n", cr2);  printf("base = %#08lx\n", (unsigned long)__djgpp_base_address);  printf("eip = %#08lx\n", __djgpp_exception_state->__eip);  printf("ebp = %#08lx\n", __djgpp_exception_state->__ebp);  printf("err = %lx\n", err_code);#endif  handle_page_fault(cr2 - __djgpp_base_address,		    err_code & 2, 		    __djgpp_exception_state->__eip,		    __djgpp_exception_state->__ebp);  return; /* and die! */}#endifstatic voidhandle_page_fault(addr address, int write, addr eip, addr ebp){  block *b;  if (SHOULD_NOT_CATCH)    {      /* If YAMD shouldn't run, we're probably inside it and so	 the crash was caused by us. */      signal(SIGSEGV, SIG_DFL);      return;    }  NO_CATCH(); /* is this really correct? */  if (!(b = find_block_by_any_addr(address)))    {      disclaimer();      return;    }  signal(SIGSEGV, SIG_DFL);  log_event(LOG_ERR, "Crash");  do_any_traceback(LOG_ERR, eip, ebp, 0);  log_detail(LOG_ERR, "Tried to %s address " POINTER_FORMAT "\n",	     (write) ? "write" : "read", address);  describe_address(LOG_ERR, address);  log_detail(LOG_ERR, "Will dump core after checking heap.\n");  check_heap();#if 0  /* Tread lightly on the core dump */  print_footer();#endif  log_flush();  return;  /* Resume the faulting instruction */}#define ENVIRON_INT 1#define ENVIRON_STRING 2struct environment_entry {  char *name;  int type;  void *valuep;};static struct environment_entry environment_entries[] = {  { "DEFAULT_ALIGNMENT", ENVIRON_INT, &default_alignment },  { "LOGFILE_NAME", ENVIRON_STRING, &logfile_name },  { "LOGFILE", ENVIRON_STRING, &logfile_name }, /* nicer for users */  { "LOGLEVEL", ENVIRON_INT, &min_log_level },  { "REPAIR_CORRUPTED", ENVIRON_INT, &repair_corrupted },  { "DIE_ON_CORRUPTED", ENVIRON_INT, &die_on_corrupted },  { "CHECK_FRONT", ENVIRON_INT, &check_front },#ifdef COMPLETE_MAGIC  { "COMPLETE_MAGIC", ENVIRON_INT, &complete_magic },#endif  { NULL, 0, NULL }};static voidparse_environment(void){  char buf[200];  struct environment_entry *env;  for (env = environment_entries; env->name != NULL; env++)    {      char *p;      strcpy(buf, ENVIRONMENT_PREFIX);      strcat(buf, env->name);      p = getenv(buf);      if (p)	{	  switch(env->type)	    {	    case ENVIRON_INT:	      {		int t;		char *tp;		t = strtol(p, &tp, 0);		if (tp)		  *(int *)env->valuep = t;		break;	      }	    case ENVIRON_STRING:	      *(const char **)env->valuep = p;	      break;	    }	}    }}/* Set LD_PRELOAD for exec'd programs, possibly to prevent children   from having YAMD loaded. */static void set_child_preload(void){  /* YAMD_CHILD_LD_PRELOAD is set for us by the shell script. */  char *s;  s = getenv("YAMD_CHILD_LD_PRELOAD");  if (s)    {      if (strlen(s) != 0)	{	  char *newbuf;	  newbuf = alloca(strlen(LD_PRELOAD_ENV) + 1 + strlen(s) + 1);	  /*                                      '='             '\0' */	  strcpy(newbuf, LD_PRELOAD_ENV);	  strcat(newbuf, "=");	  strcat(newbuf, s);	  putenv(newbuf);	}      else	{	  putenv(LD_PRELOAD_ENV); /* unset it */	}    }}/* Return process size in K. */#ifdef __linux__static unsigned long process_size(void){  FILE *f;  unsigned long s;  char buf[100];  f = fopen("/proc/self/status", "r");  if (!f)    return 0;  while (fgets(buf, 100, f) != NULL)    {      if (sscanf(buf, "VmSize: %lu", &s) == 1)	return s;    }  return 0;}#endif#ifdef __DJGPP__static unsigned long process_size(void){  /* Probably not accurate.  mprotect(PROT_NONE) will uncommit pages,     meaning they will not be swapped out and are effectively freed     (since when physical memory becomes full they will be discarded     and reused).  This has the effect of creating holes in the memory     map, so we're not actually using all the memory in this range. */  return (((unsigned long)sbrk(0)) - 0x1000) / 1024;}#endifstatic void print_footer(void){  time_t t;  time(&t);  /* ctime's string ends in \n */  log_printf("\n*** Finished at %s", ctime(&t));    log_printf("Allocated a grand total of %lu bytes\n",	  (unsigned long)user_allocated);  log_printf("%lu allocations\n", n_allocations);  log_printf("Average of %lu bytes per allocation\n",	  user_allocated / (n_allocations ? n_allocations : 1));  log_printf("Max bytes allocated at one time: %lu\n",	  (unsigned long)max_user_allocated);  log_printf("%lu K alloced internally / %lu K mapped now / %lu K max\n",	  (unsigned long)internal_allocated / 1024,	  (unsigned long)internal_mapped / 1024,	  (unsigned long)max_internal_mapped / 1024);#ifdef HASH_PROFILE  hash_profile();#endif  log_printf("Virtual program size is %lu K\n", process_size());  log_printf("End.\n");}static void check_memory_leaks(void){  block *p;  int nleaks = 0;  unsigned long nbytes = 0;  for_each_block(p)    {      /* Don't complain that libc is leaking memory. */      if (p->who_alloced != BY_ALLOCA	  && p->who_alloced != BY_LITE	  && p->who_freed == BY_NONE)	{	  nleaks++;	  nbytes += p->user_size;	  log_event(LOG_WARN, "Memory leak");	  describe_block(LOG_WARN, p);	}    }  if (nleaks)    {      log_event(LOG_WARN, "Total memory leaks:");      log_detail(LOG_WARN, "%d unfreed allocations totaling %lu bytes\n",		 nleaks, nbytes);    }}static void print_header(void){  time_t t;  log_printf("YAMD version %s\n", YAMD_VERSION);  log_printf("Starting run: ");#ifdef __linux__  {    FILE *cmdline;    char buf[PATH_MAX];    int len;    cmdline = fopen("/proc/self/cmdline", "r");    if (cmdline)      {	int c;	while ((c = getc(cmdline)) != EOF)	  {	    if (c == 0) c = ' '; /* null separation in use */	    /* Well, this oughta be plenty slow.  Would log_putc be	       a good idea, or should I use a real buffer here? */	    log_printf("%c", c);	  }	fclose(cmdline);      }    else      log_printf("<unknown>");    log_printf("\n");    /* This will only be useful if they have the new dcache       in the kernel (since mid 2.1 but not in 2.0). */    len = readlink("/proc/self/exe", buf, PATH_MAX);    if (len < 0)      strcpy(buf, "<unknown>");    else      buf[len] = '\0'; /* readlink does not null-terminate. */    log_printf("Executable: %s\n", buf);  }#endif#ifdef __DJGPP__  {    int i;    for (i = 0; i < __crt0_argc; i++)      log_printf("%s ", __crt0_argv[i]);    log_printf("\nExecutable: %s\n", __crt0_argv[0]);  }#endif  log_printf("Virtual program size is %lu K\n", process_size());  time(&t);  log_printf("Time is %s\n", ctime(&t));#define PRINT_VAR(v) log_printf("%s = %d\n", #v, v)  PRINT_VAR(default_alignment);  PRINT_VAR(min_log_level);  PRINT_VAR(repair_corrupted);  PRINT_VAR(die_on_corrupted);  PRINT_VAR(check_front);#ifdef COMPLETE_MAGIC  PRINT_VAR(complete_magic);#endif#undef PRINT_VAR}#ifdef USE_LIBC_HOOKSstatic void start_catching(void){  OK_CATCH();}void (*__malloc_initialize_hook)(void) = start_catching;#endif/* HACK HACK HACK HACK HACK HACK HACK *//* We want `startup' to be run before any constructors, and `finish'   after all destructors and `atexit' functions.  The order depends in   part on link order.  Therefore we call these from all possible   places, and get the first or last as appropriate. */void __yamd_maybe_startup(void){  static int have_run = 0;  if (!have_run)    {      have_run = 1;      atexit(__yamd_maybe_finish);      startup();    }  else    return;}void __yamd_maybe_finish(void){  static int tries = 0;  if (++tries == TRIES_FOR_FINISH) /* This is the last try */    finish();  else    return;}/* This file will be linked either first or last, so let's have a shot   at constructing. */static void construct(void) __attribute__((constructor));static void construct(void) { __yamd_maybe_startup(); }static void destruct(void) __attribute__((destructor));static void destruct(void) { __yamd_maybe_finish(); }static void startup(void) {  static int initted = 0;  if (initted)    {      fprintf(stderr, "Initted multiple times! Can't happen\n");      return;    }  initted = 1;  /* We are in lite mode. */  parse_environment();  set_child_preload();   if (strcmp(logfile_name, "-") == 0)    {      log_fd = 2;    }  else    {      /* Would other perms. be a good idea? */      log_fd = open(logfile_name, O_WRONLY | O_CREAT | O_TRUNC, 0600);       if (log_fd < 0)	{	  perror(logfile_name);	  return;	}    }  print_header();#ifdef __DJGPP__#ifdef DJGPP_SIGNAL#ifdef DEBUG  printf("Running in ring %d\n", get_ring());#endif /* DEBUG */  if (get_ring() == 0)    signal(SIGSEGV, sigsegv_handler);#endif /* DJGPP_SIGNAL */#else  signal(SIGSEGV, (void (*)(int))sigsegv_handler);  #endif /* __DJGPP__ */  mode = FULL_MODE; /* go go go! */}static void finish(void){  mode = LITE_MODE;  signal(SIGSEGV, SIG_DFL);  check_heap(); /* One last time... */  check_memory_leaks();  print_footer();  log_flush();  close(log_fd);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -