📄 gwmem-check.c
字号:
(sizeof(p) == sizeof(long) && (p_ul == NEW_AREA_PATTERN || p_ul == FREE_AREA_PATTERN || p_ul == START_MARK_PATTERN || p_ul == END_MARK_PATTERN)); if (slow || suspicious_pointer) { /* Extra check, which does not touch the (perhaps not allocated) * memory area. It's slow, but may help pinpoint problems that * would otherwise cause segfaults. */ for (index = 0; index < num_allocations; index++) { if (allocated[index].area == p) break; } if (index == num_allocations) { error(0, "Area %p not found in allocation table.", p); return NULL; } } index = check_startmark(p); if (index >= 0 && index < num_allocations && allocated[index].area == p) { area = &allocated[index]; if (check_endmark(p, area->area_size) < 0) { error(0, "End marker was damaged for area %p", p); dump_area(area); } return area; } error(0, "Start marker was damaged for area %p", p); for (index = 0; index < num_allocations; index++) { if (allocated[index].area == p) { area = &allocated[index]; dump_area(area); return area; } } error(0, "Could not find area information."); return NULL;}static void change_total_size(long change){ total_size += change; if (total_size > highest_total_size) highest_total_size = total_size;}static struct area *record_allocation(unsigned char *p, size_t size, const char *filename, long lineno, const char *function){ struct area *area; static struct area empty_area; if (num_allocations == MAX_ALLOCATIONS) { panic(0, "Too many concurrent allocations."); } area = &allocated[num_allocations]; *area = empty_area; area->area = p; area->area_size = size; area->max_size = size; area->allocator.filename = filename; area->allocator.lineno = lineno; area->allocator.function = function; startmark(area->area, num_allocations); endmark(area->area, area->area_size); num_allocations++; if (num_allocations > highest_num_allocations) highest_num_allocations = num_allocations; change_total_size(size); return area;}static void remove_allocation(struct area *area){ change_total_size(-1*area->area_size); num_allocations--; if (area == &allocated[num_allocations]) return; check_marks(&allocated[num_allocations], num_allocations); *area = allocated[num_allocations]; startmark(area->area, area - allocated);}static void drop_from_free_ring(long index){ struct area *area; area = &free_ring[index]; if (check_marks(area, index) < 0 || !untouched(area->area, area->area_size, FREE_AREA_PATTERN)) { error(0, "Freed area %p has been tampered with.", area->area); dump_area(area); } free((unsigned char *)area->area - MARKER_SIZE);}static void put_on_free_ring(struct area *area){ /* Simple case: We're still filling the free ring. */ if (free_ring_len < FREE_RING_SIZE) { free_ring[free_ring_len] = *area; startmark(area->area, free_ring_len); free_ring_len++; return; } /* Normal case: We need to check and release a free ring entry, * then put this one in its place. */ drop_from_free_ring(free_ring_start); free_ring[free_ring_start] = *area; startmark(area->area, free_ring_start); free_ring_start = (free_ring_start + 1) % FREE_RING_SIZE;}static void free_area(struct area *area){ fill(area->area, area->area_size, FREE_AREA_PATTERN); put_on_free_ring(area); remove_allocation(area);}void gw_check_init_mem(int slow_flag){ mutex_init_static(&gwmem_lock); slow = slow_flag; initialized = 1;}void gw_check_shutdown(void){ mutex_destroy(&gwmem_lock); initialized = 0;}void *gw_check_malloc(size_t size, const char *filename, long lineno, const char *function){ unsigned char *p; gw_assert(initialized); /* ANSI C89 says malloc(0) is implementation-defined. Avoid it. */ gw_assert(size > 0); p = malloc(size + 2 * MARKER_SIZE); if (p == NULL) panic(errno, "Memory allocation of %d bytes failed.", size); p += MARKER_SIZE; lock(); fill(p, size, NEW_AREA_PATTERN); record_allocation(p, size, filename, lineno, function); unlock(); return p;}void *gw_check_realloc(void *p, size_t size, const char *filename, long lineno, const char *function){ struct area *area; if (p == NULL) return gw_check_malloc(size, filename, lineno, function); gw_assert(initialized); gw_assert(size > 0); lock(); area = find_area(p); if (!area) { unlock(); panic(0, "Realloc called on non-allocated area"); } if (size == area->area_size) { /* No changes */ } else if (size <= area->max_size) { change_total_size(size - area->area_size); area->area_size = size; endmark(p, size); } else if (size > area->max_size) { /* The current block is not large enough for the reallocation. * We will allocate a new block, copy the data over, and free * the old block. We round the size up to a power of two, * to prevent frequent reallocations. */ struct area *new_area; size_t new_size; unsigned char *new_p; new_size = round_pow2(size + 2 * MARKER_SIZE); new_p = malloc(new_size); new_size -= 2 * MARKER_SIZE; new_p += MARKER_SIZE; memcpy(new_p, p, area->area_size); fill(new_p + area->area_size, size - area->area_size, NEW_AREA_PATTERN); new_area = record_allocation(new_p, size, area->allocator.filename, area->allocator.lineno, area->allocator.function); new_area->max_size = new_size; free_area(area); p = new_p; area = new_area; } area->reallocator.filename = filename; area->reallocator.lineno = lineno; area->reallocator.function = function; unlock(); return p;}void gw_check_free(void *p, const char *filename, long lineno, const char *function){ struct area *area; gw_assert(initialized); if (p == NULL) return; lock(); area = find_area(p); if (!area) { unlock(); panic(0, "Free called on non-allocated area"); } free_area(area); unlock();}char *gw_check_strdup(const char *str, const char *filename, long lineno, const char *function){ char *copy; gw_assert(initialized); gw_assert(str != NULL); copy = gw_check_malloc(strlen(str) + 1, filename, lineno, function); strcpy(copy, str); return copy;}void *gw_check_claim_area(void *p, const char *filename, long lineno, const char *function){ struct area *area; /* Allow this for the convenience of wrapper macros. */ if (p == NULL) return NULL; lock(); area = find_area(p); if (!area) { unlock(); panic(0, "Claim_area called on non-allocated area"); } area->claimer.filename = filename; area->claimer.lineno = lineno; area->claimer.function = function; unlock(); /* For convenience of calling macros */ return p;}void gw_check_check_leaks(void){ long calculated_size; long index; gw_assert(initialized); lock(); for (index = 0; index < free_ring_len; index++) { drop_from_free_ring(index); } free_ring_len = 0; calculated_size = 0; for (index = 0; index < num_allocations; index++) { calculated_size += allocated[index].area_size; } gw_assert(calculated_size == total_size); debug("gwlib.gwmem", 0, "----------------------------------------"); debug("gwlib.gwmem", 0, "Current allocations: %ld areas, %ld bytes", num_allocations, total_size); debug("gwlib.gwmem", 0, "Highest number of allocations: %ld areas", highest_num_allocations); debug("gwlib.gwmem", 0, "Highest memory usage: %ld bytes", highest_total_size); for (index = 0; index < num_allocations; index++) { check_marks(&allocated[index], index); dump_area(&allocated[index]); } unlock();}int gw_check_is_allocated(void *p){ struct area *area; lock(); area = find_area(p); unlock(); return area != NULL;}long gw_check_area_size(void *p){ struct area *area; size_t size; lock(); area = find_area(p); if (!area) { unlock(); warning(0, "Area_size called on non-allocated area %p", p); return -1; } size = area->area_size; unlock(); return size;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -