📄 dmalloc_t.c
字号:
/* * Test program for malloc code * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: dmalloc_t.c,v 1.117 2004/10/19 14:50:44 gray Exp $ *//* * Test program for the malloc library. Current it is interactive although * should be script based. */#include <stdio.h> /* for stdin */#if HAVE_STDLIB_H# include <stdlib.h> /* for atoi + */#endif#if HAVE_STRING_H# include <string.h>#endif#if HAVE_UNISTD_H# include <unistd.h>#endif#include "conf.h"#include "compat.h" /* for loc_snprintf */#if HAVE_TIME# ifdef TIME_INCLUDE# include TIME_INCLUDE# endif#endif#include "dmalloc.h"#include "dmalloc_argv.h"#include "dmalloc_rand.h"/* * NOTE: these are only needed to test certain features of the library. */#include "debug_tok.h"#include "error_val.h"#include "heap.h" /* for external testing */#define INTER_CHAR 'i'#define DEFAULT_ITERATIONS 10000#define MAX_POINTERS 1024#define MAX_ALLOC (1024 * 1024)#define MIN_AVAIL 10/* pointer tracking structure */typedef struct pnt_info_st { long pi_crc; /* crc of storage */ int pi_size; /* size of storage */ void *pi_pnt; /* pnt to storage */ struct pnt_info_st *pi_next; /* pnt to next */} pnt_info_t;static pnt_info_t *pointer_grid;/* argument variables */static int default_iter_n = DEFAULT_ITERATIONS; /* # of iters */static char *env_string = NULL; /* env options */static int interactive_b = ARGV_FALSE; /* interactive flag */static int log_trans_b = ARGV_FALSE; /* log transactions */static int no_special_b = ARGV_FALSE; /* no-special flag */static int max_alloc = MAX_ALLOC; /* amt of mem to use */static int max_pointers = MAX_POINTERS; /* # of pnts to use */static int random_debug_b = ARGV_FALSE; /* random flag */static int silent_b = ARGV_FALSE; /* silent flag */static unsigned int seed_random = 0; /* random seed */static int verbose_b = ARGV_FALSE; /* verbose flag */static argv_t arg_list[] = { { INTER_CHAR, "interactive", ARGV_BOOL_INT, &interactive_b, NULL, "turn on interactive mode" }, { 'e', "env-string", ARGV_CHAR_P, &env_string, "string", "string of env commands to set" }, { 'l', "log-trans", ARGV_BOOL_INT, &log_trans_b, NULL, "log transactions via tracking-func" }, { 'm', "max-alloc", ARGV_INT, &max_alloc, "bytes", "maximum allocation to test" }, { 'n', "no-special", ARGV_BOOL_INT, &no_special_b, NULL, "do not run special tests" }, { 'p', "max-pointers", ARGV_INT, &max_pointers, "pointers", "number of pointers to test" }, { 'r', "random-debug", ARGV_BOOL_INT, &random_debug_b, NULL, "randomly change debug flag" }, { 's', "silent", ARGV_BOOL_INT, &silent_b, NULL, "do not display messages" }, { 'S', "seed-random", ARGV_U_INT, &seed_random, "number", "seed for random function" }, { 't', "times", ARGV_INT, &default_iter_n, "number", "number of iterations to run" }, { 'v', "verbose", ARGV_BOOL_INT, &verbose_b, NULL, "enables verbose messages" }, { ARGV_LAST }};/* * Hexadecimal STR to integer translation */static long hex_to_long(char *str){ long ret; /* strip off spaces */ for (; *str == ' ' || *str == '\t'; str++) { } /* skip a leading 0[xX] */ if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X')) { str += 2; } for (ret = 0;; str++) { if (*str >= '0' && *str <= '9') { ret = ret * 16 + (*str - '0'); } else if (*str >= 'a' && *str <= 'f') { ret = ret * 16 + (*str - 'a' + 10); } else if (*str >= 'A' && *str <= 'F') { ret = ret * 16 + (*str - 'A' + 10); } else { break; } } return ret;}/* * Read an address from the user */static void *get_address(void){ char line[80]; void *pnt; do { (void)printf("Enter a hex address: "); if (fgets(line, sizeof(line), stdin) == NULL) { return NULL; } } while (line[0] == '\0'); pnt = (void *)hex_to_long(line); return pnt;}/* * Free a slot from the used_p list and put it on the free list */static void free_slot(const int iter_c, pnt_info_t *slot_p, pnt_info_t **used_pp, pnt_info_t **free_pp){ pnt_info_t *this_p, *prev_p; if (verbose_b) { (void)printf("%d: free'd %d bytes from slot %d (%#lx)\n", iter_c + 1, slot_p->pi_size, slot_p - pointer_grid, (long)slot_p->pi_pnt); } slot_p->pi_pnt = NULL; /* find pnt in the used list */ for (this_p = *used_pp, prev_p = NULL; this_p != NULL; prev_p = this_p, this_p = this_p->pi_next) { if (this_p == slot_p) { break; } } if (prev_p == NULL) { *used_pp = slot_p->pi_next; } else { prev_p->pi_next = slot_p->pi_next; } slot_p->pi_next = *free_pp; *free_pp = slot_p;}/* * Try ITER_N random program iterations, returns 1 on success else 0 */static int do_random(const int iter_n){ unsigned int flags; int iter_c, prev_errno, amount, max_avail, free_c; int final = 1; char *chunk_p; pnt_info_t *free_p, *used_p = NULL; pnt_info_t *pnt_p; max_avail = max_alloc; flags = dmalloc_debug_current(); pointer_grid = (pnt_info_t *)malloc(sizeof(pnt_info_t) * max_pointers); if (pointer_grid == NULL) { (void)printf("%s: problems allocating space for %d pointer slots.\n", argv_program, max_pointers); return 0; } /* initialize free list */ free_p = pointer_grid; for (pnt_p = pointer_grid; pnt_p < pointer_grid + max_pointers; pnt_p++) { pnt_p->pi_size = 0; pnt_p->pi_pnt = NULL; pnt_p->pi_next = pnt_p + 1; } /* redo the last next pointer */ (pnt_p - 1)->pi_next = NULL; free_c = max_pointers; prev_errno = ERROR_NONE; for (iter_c = 0; iter_c < iter_n;) { int which_func, which; if (dmalloc_errno != prev_errno && ! silent_b) { (void)printf("ERROR: iter %d, %s (err %d)\n", iter_c, dmalloc_strerror(dmalloc_errno), dmalloc_errno); prev_errno = dmalloc_errno; final = 0; } /* special case when doing non-linear stuff, sbrk took all memory */ if (max_avail < MIN_AVAIL && free_p == NULL) { break; } if (random_debug_b) { unsigned int new_flag; which = _dmalloc_rand() % (sizeof(int) * 8); new_flag = 1 << which; flags ^= new_flag; if (verbose_b) { (void)printf("%d: debug flags = %#x\n", iter_c + 1, flags); } dmalloc_debug(flags); } /* decide whether to malloc a new pointer or free/realloc an existing */ which = _dmalloc_rand() % 4; if ((free_p == NULL || which == 3 || max_avail < MIN_AVAIL || free_c == max_pointers) && used_p != NULL) { /* choose a random slot to free */ which = _dmalloc_rand() % (max_pointers - free_c); for (pnt_p = used_p; which > 0; which--) { pnt_p = pnt_p->pi_next; } free(pnt_p->pi_pnt); free_slot(iter_c, pnt_p, &used_p, &free_p); free_c++; if (verbose_b) { (void)printf("%d: free'd %d bytes from slot %d (%#lx)\n", iter_c + 1, pnt_p->pi_size, pnt_p - pointer_grid, (long)pnt_p->pi_pnt); } max_avail += pnt_p->pi_size; iter_c++; continue; } /* sanity check */ if (free_p == NULL) { (void)fprintf(stderr, "%s: problem with test program free list\n", argv_program); exit(1); } /* rest are allocations */ amount = _dmalloc_rand() % (max_avail / 2);#if ALLOW_ALLOC_ZERO_SIZE == 0 if (amount == 0) { amount = 1; }#endif which_func = _dmalloc_rand() % 7; switch (which_func) { /* malloc */ case 0: pnt_p = free_p; pnt_p->pi_pnt = malloc(amount); if (verbose_b) { (void)printf("%d: malloc %d of max %d into slot %d. got %#lx\n", iter_c + 1, amount, max_avail, pnt_p - pointer_grid, (long)pnt_p->pi_pnt); } break; /* calloc */ case 1: pnt_p = free_p; pnt_p->pi_pnt = calloc(amount, sizeof(char)); if (verbose_b) { (void)printf("%d: calloc %d of max %d into slot %d. got %#lx\n", iter_c + 1, amount, max_avail, pnt_p - pointer_grid, (long)pnt_p->pi_pnt); } /* test the returned block to make sure that is has been cleared */ if (pnt_p->pi_pnt != NULL) { for (chunk_p = pnt_p->pi_pnt; chunk_p < (char *)pnt_p->pi_pnt + amount; chunk_p++) { if (*chunk_p != '\0') { if (! silent_b) { (void)printf("calloc of %d was not fully zeroed on iteration #%d\n", amount, iter_c + 1); } break; } } } break; /* realloc */ case 2: if (free_c == max_pointers) { continue; } which = _dmalloc_rand() % (max_pointers - free_c); for (pnt_p = used_p; which > 0; which--) { pnt_p = pnt_p->pi_next; } pnt_p->pi_pnt = realloc(pnt_p->pi_pnt, amount); /* * note that we've free the old size, we'll account for the * alloc below */ max_avail += pnt_p->pi_size; if (verbose_b) { (void)printf("%d: realloc %d from %d of max %d slot %d. got %#lx\n", iter_c + 1, amount, pnt_p->pi_size, max_avail, pnt_p - pointer_grid, (long)pnt_p->pi_pnt); } if (amount == 0) { free_slot(iter_c, pnt_p, &used_p, &free_p); free_c++; pnt_p = NULL; continue; } break; /* recalloc */ case 3: if (free_c == max_pointers) { continue; } which = _dmalloc_rand() % (max_pointers - free_c); for (pnt_p = used_p; which > 0; which--) { pnt_p = pnt_p->pi_next; } pnt_p->pi_pnt = recalloc(pnt_p->pi_pnt, amount); /* * note that we've free the old size, we'll account for the * alloc below */ max_avail += pnt_p->pi_size; if (verbose_b) { (void)printf("%d: recalloc %d from %d of max %d slot %d. got %#lx\n", iter_c + 1, amount, pnt_p->pi_size, max_avail, pnt_p - pointer_grid, (long)pnt_p->pi_pnt); } /* test the returned block to make sure that is has been cleared */ if (pnt_p->pi_pnt != NULL && amount > pnt_p->pi_size) { for (chunk_p = (char *)pnt_p->pi_pnt + pnt_p->pi_size; chunk_p < (char *)pnt_p->pi_pnt + amount; chunk_p++) { if (*chunk_p != '\0') { if (! silent_b) { (void)printf("recalloc %d from %d was not fully zeroed on iteration #%d\n", amount, pnt_p->pi_size, iter_c + 1); } break; } } } if (amount == 0) { free_slot(iter_c, pnt_p, &used_p, &free_p); free_c++; pnt_p = NULL; continue; } break; /* valloc */ case 4: pnt_p = free_p; pnt_p->pi_pnt = valloc(amount); if (verbose_b) { (void)printf("%d: valloc %d of max %d into slot %d. got %#lx\n", iter_c + 1, amount, max_avail, pnt_p - pointer_grid, (long)pnt_p->pi_pnt); } break; /* sbrk */ case 5: /* do it less often then the other functions */ which = _dmalloc_rand() % 5; if (which == 3 && amount > 0) { void *mem; mem = _dmalloc_heap_alloc(amount); if (verbose_b) { (void)printf("%d: heap alloc %d of max %d bytes. got %#lx\n", iter_c + 1, amount, max_avail, (long)mem); } iter_c++; } /* don't store the memory */ continue; break; /* heap check in the middle */ case 6: /* do it less often then the other functions */ which = _dmalloc_rand() % 20; if (which == 7) { if (dmalloc_verify(NULL /* check all heap */) != DMALLOC_NOERROR) { if (! silent_b) { (void)printf("%d: ERROR dmalloc_verify failed\n", iter_c + 1); } final = 0; } iter_c++; } continue; break; default: continue; break; } if (pnt_p->pi_pnt == NULL) { if (! silent_b) { (void)printf("%d: ERROR allocation of %d returned error\n", iter_c + 1, amount); } final = 0; iter_c++; continue; } /* set the size and take it off the free-list and put on used list */ pnt_p->pi_size = amount; if (pnt_p == free_p) { free_p = pnt_p->pi_next; pnt_p->pi_next = used_p; used_p = pnt_p; free_c--; } max_avail -= amount; iter_c++; continue; } /* free used pointers */ for (pnt_p = pointer_grid; pnt_p < pointer_grid + max_pointers; pnt_p++) { if (pnt_p->pi_pnt != NULL) { free(pnt_p->pi_pnt); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -