📄 chunk.c
字号:
int final = 1; if (BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_TRANS)) { dmalloc_message("checking heap"); } heap_check_c++; /* * first, run through all of the admin structures and check for * validity */ for (level_c = 0; level_c < MAX_SKIP_LEVEL; level_c++) { unsigned int *magic3_p, magic3; /* run through the blocks and test them */ for (block_p = entry_blocks[level_c]; block_p != NULL; block_p = block_p->eb_next_p) { /* better be in the heap */ if (! IS_IN_HEAP(block_p)) { dmalloc_errno = ERROR_ADMIN_LIST; dmalloc_error("_dmalloc_chunk_heap_check"); return 0; } /* get the magic3 at the end of the block */ magic3_p = (unsigned int *)((char *)block_p + BLOCK_SIZE - sizeof(*magic3_p)); memcpy(&magic3, magic3_p, sizeof(magic3)); /* check magics */ if (block_p->eb_magic1 != ENTRY_BLOCK_MAGIC1 || block_p->eb_magic2 != ENTRY_BLOCK_MAGIC2 || magic3 != ENTRY_BLOCK_MAGIC3) { dmalloc_errno = ERROR_ADMIN_LIST; dmalloc_error("_dmalloc_chunk_heap_check"); return 0; } /* check for a valid level */ if (block_p->eb_level_n != level_c) { dmalloc_errno = ERROR_ADMIN_LIST; dmalloc_error("_dmalloc_chunk_heap_check"); return 0; } /* now we look up the block and make sure it exists and is valid */ slot_p = find_address(block_p, 1 /* exact */, skip_update); if (slot_p == NULL) { dmalloc_errno = ERROR_ADMIN_LIST; dmalloc_error("_dmalloc_chunk_heap_check"); return 0; } if ((! BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_ADMIN)) || slot_p->sa_mem != block_p || slot_p->sa_total_size != BLOCK_SIZE || slot_p->sa_level_n != level_c) { dmalloc_errno = ERROR_ADMIN_LIST; dmalloc_error("_dmalloc_chunk_heap_check"); return 0; } /* * NOTE: we could now check each of the entries in the block to * make sure that they are valid and on the used or free list */ } } /* * Now run through the used pointers and check each one. */ for (slot_p = skip_address_list->sa_next_p[0]; ; slot_p = slot_p->sa_next_p[0]) { skip_alloc_t *block_slot_p; /* * switch to the free list in the middle after we've checked the * used pointer slots */ if (slot_p == NULL) { checking_list_c++; if (checking_list_c == 1) { slot_p = skip_free_list->sa_next_p[0]; }#if FREED_POINTER_DELAY else if (checking_list_c == 2) { slot_p = free_wait_list_head; }#endif else { /* we are done */ break; } if (slot_p == NULL) { break; } } /* better be in the heap */ if (! IS_IN_HEAP(slot_p)) { dmalloc_errno = ERROR_ADDRESS_LIST; dmalloc_error("_dmalloc_chunk_heap_check"); return 0; } /* * now we look up the slot pointer itself and make sure it exists * in a valid block */ block_slot_p = find_address(slot_p, 0 /* not exact pointer */, skip_update); if (block_slot_p == NULL) { dmalloc_errno = ERROR_ADMIN_LIST; dmalloc_error("_dmalloc_chunk_heap_check"); return 0; } /* point at the block */ block_p = block_slot_p->sa_mem; /* check block magic */ if (block_p->eb_magic1 != ENTRY_BLOCK_MAGIC1) { dmalloc_errno = ERROR_ADDRESS_LIST; dmalloc_error("_dmalloc_chunk_heap_check"); return 0; } /* make sure the slot level matches */ if (slot_p->sa_level_n != block_p->eb_level_n) { dmalloc_errno = ERROR_ADDRESS_LIST; dmalloc_error("_dmalloc_chunk_heap_check"); return 0; } /* now check the allocation */ if (checking_list_c == 0) { ret = check_used_slot(slot_p, NULL /* no user pnt */, 0 /* loose pnt checking */); if (! ret) { /* error set in check_slot */ log_error_info(NULL, 0, NULL, slot_p, "checking user pointer", "_dmalloc_chunk_heap_check"); /* not a critical error */ final = 0; } } else { ret = check_free_slot(slot_p); if (! ret) { /* error set in check_slot */ log_error_info(NULL, 0, NULL, slot_p, "checking free pointer", "_dmalloc_chunk_heap_check"); /* not a critical error */ final = 0; } } } return final;}/* * int _dmalloc_chunk_pnt_check * * DESCRIPTION: * * Run extensive tests on a pointer. * * RETURNS: * * Success - 1 if the pointer is okay * * Failure - 0 if not * * ARGUMENTS: * * func -> Function string which is checking the pointer. * * user_pnt -> Pointer we are checking. * * exact_b -> Set to 1 to find the pointer specifically. Otherwise we * can find the pointer inside of an allocation. * * min_size -> Make sure that pnt can hold at least that many bytes. * If -1 then do a strlen + 1 for the \0. If 0 then ignore. */int _dmalloc_chunk_pnt_check(const char *func, const void *user_pnt, const int exact_b, const int min_size){ skip_alloc_t *slot_p; unsigned int min; pnt_info_t pnt_info; if (BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_TRANS)) { if (func == NULL) { dmalloc_message("checking pointer '%#lx'", (unsigned long)user_pnt); } else { dmalloc_message("checking func '%s' pointer '%#lx'", func, (unsigned long)user_pnt); } } /* try to find the address */ slot_p = find_address(user_pnt, 0 /* not exact pointer */, skip_update); if (slot_p == NULL) { if (exact_b) { dmalloc_errno = ERROR_NOT_FOUND; log_error_info(NULL, 0, user_pnt, NULL, "pointer-check", func); return 0; } else { dmalloc_errno = ERROR_NONE; return 1; } } /* now make sure that the user slot is valid */ if (! check_used_slot(slot_p, user_pnt, exact_b)) { /* dmalloc_error set in check_used_slot */ log_error_info(NULL, 0, user_pnt, slot_p, "pointer-check", func); return 0; } /* if min_size is < 0 then do a strlen and take into account the \0 */ if (min_size != 0) { if (min_size > 0) { min = min_size; } else { /* length of the string + 1 for the \0 */ min = strlen((char *)user_pnt) + 1; } /* get info about the pointer */ get_pnt_info(slot_p, &pnt_info); /* are we within bounds on the user pointer and size */ if ((char *)user_pnt < (char *)pnt_info.pi_user_start || (char *)user_pnt + min > (char *)pnt_info.pi_user_bounds) { dmalloc_errno = ERROR_WOULD_OVERWRITE; log_error_info(NULL, 0, user_pnt, slot_p, "pointer-check", func); return 0; } } return 1;}/************************** low-level user functions *************************//* * void *_dmalloc_chunk_malloc * * DESCRIPTION: * * Allocate a chunk of memory. * * RETURNS: * * Success - Valid pointer. * * Failure - NULL * * ARGUMENTS: * * file -> File-name or return-address location of the allocation. * * line -> Line-number location of the allocation. * * size -> Number of bytes to allocate. * * func_id -> Calling function-id as defined in dmalloc.h. * * alignment -> If greater than 0 then try to align the returned * block. */void *_dmalloc_chunk_malloc(const char *file, const unsigned int line, const unsigned long size, const int func_id, const unsigned int alignment){ unsigned long needed_size; int valloc_b = 0, memalign_b = 0, fence_b = 0; char where_buf[MAX_FILE_LENGTH + 64], disp_buf[64]; skip_alloc_t *slot_p; pnt_info_t pnt_info; const char *trans_log; /* counts calls to malloc */ if (func_id == DMALLOC_FUNC_CALLOC) { func_calloc_c++; } else if (alignment == BLOCK_SIZE) { func_valloc_c++; valloc_b = 1; } else if (alignment > 0) { func_memalign_c++; memalign_b = 1; } else if (func_id == DMALLOC_FUNC_NEW) { func_new_c++; } else if (func_id != DMALLOC_FUNC_REALLOC && func_id != DMALLOC_FUNC_RECALLOC) { func_malloc_c++; } #if ALLOW_ALLOC_ZERO_SIZE == 0 if (size == 0) { dmalloc_errno = ERROR_BAD_SIZE; log_error_info(file, line, NULL, NULL, "bad zero byte allocation request", "malloc"); return MALLOC_ERROR; }#endif #if LARGEST_ALLOCATION /* have we exceeded the upper bounds */ if (size > LARGEST_ALLOCATION) { dmalloc_errno = ERROR_TOO_BIG; log_error_info(file, line, NULL, NULL, "allocation too big", "malloc"); return MALLOC_ERROR; }#endif needed_size = size; /* adjust the size */ if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FENCE)) { needed_size += FENCE_OVERHEAD_SIZE; fence_b = 1; /* * If the user is requesting a page-aligned block of data then we * will need another block below the allocation just for the fence * information. Ugh. */ if (valloc_b) { needed_size += BLOCK_SIZE; } } else if (valloc_b && needed_size <= BLOCK_SIZE / 2) { /* * If we are valloc-ing, make sure that we get a blocksized chunk * because they are always block aligned. We know here that fence * posting is not on otherwise it would have been set above. */ needed_size = BLOCK_SIZE; } /* get some space for our memory */ slot_p = get_memory(needed_size); if (slot_p == NULL) { /* errno set in get_slot */ return MALLOC_ERROR; } if (fence_b) { BIT_SET(slot_p->sa_flags, ALLOC_FLAG_FENCE); } if (valloc_b) { BIT_SET(slot_p->sa_flags, ALLOC_FLAG_VALLOC); } slot_p->sa_user_size = size; /* initialize the bblocks */ alloc_cur_given += slot_p->sa_total_size; alloc_max_given = MAX(alloc_max_given, alloc_cur_given); get_pnt_info(slot_p, &pnt_info); /* clear the allocation */ clear_alloc(slot_p, &pnt_info, 0 /* no old-size */, func_id); slot_p->sa_file = file; slot_p->sa_line = line; slot_p->sa_use_iter = _dmalloc_iter_c;#if LOG_PNT_SEEN_COUNT slot_p->sa_seen_c++;#endif#if LOG_PNT_ITERATION slot_p->sa_iteration = _dmalloc_iter_c;#endif if (BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_ELAPSED_TIME) || BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_CURRENT_TIME)) {#if LOG_PNT_TIMEVAL GET_TIMEVAL(slot_p->sa_timeval);#else#if LOG_PNT_TIME slot_p->sa_time = time(NULL);#endif#endif } #if LOG_PNT_THREAD_ID slot_p->sa_thread_id = THREAD_GET_ID();#endif /* do we need to print transaction info? */ if (BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_TRANS)) { switch (func_id) { case DMALLOC_FUNC_CALLOC: trans_log = "calloc"; break; case DMALLOC_FUNC_MEMALIGN: trans_log = "memalign"; break; case DMALLOC_FUNC_VALLOC: trans_log = "valloc"; break; default: trans_log = "alloc"; break; } dmalloc_message("*** %s: at '%s' for %ld bytes, got '%s'", trans_log, _dmalloc_chunk_desc_pnt(where_buf, sizeof(where_buf), file, line), size, display_pnt(pnt_info.pi_user_start, slot_p, disp_buf, sizeof(disp_buf))); } #if MEMORY_TABLE_TOP_LOG _dmalloc_table_insert(mem_table_alloc, MEM_ALLOC_ENTRIES, file, line, size, &mem_table_alloc_c);#endif /* monitor current allocation level */ alloc_current += size; alloc_maximum = MAX(alloc_maximum, alloc_current); _dmalloc_alloc_total += size; alloc_one_max = MAX(alloc_one_max, size); /* monitor pointer usage */ alloc_cur_pnts++; alloc_max_pnts = MAX(alloc_max_pnts, alloc_cur_pnts); alloc_tot_pnts++; return pnt_info.pi_user_start;}/* * int _dmalloc_chunk_free * * DESCRIPTION: * * Free a user pointer from the heap. * * RETURNS: * * Success - FREE_NOERROR * * Failure - FREE_ERROR * * ARGUMENTS: * * file -> File-name or return-address location of the allocation. * * line -> Line-number location of the allocation. * * user_pnt -> Pointer we are freeing. * * func_id -> Function ID */int _dmalloc_chunk_free(const char *file, const unsigned int line, void *user_pnt, const int func_id){ char where_buf[MAX_FILE_LENGTH + 64]; char where_buf2[MAX_FILE_LENGTH + 64], disp_buf[64]; skip_alloc_t *slot_p, *update_p; /* counts calls to free */ if (func_id == DMALLOC_FUNC_DELETE) { func_delete_c++; } else if (func_id == DMALLOC_FUNC_REALLOC || func_id == DMALLOC_FUNC_RECALLOC) { /* ignore these because they will alredy be accounted for in realloc */ } else { func_free_c++; } if (user_pnt == NULL) { #if ALLOW_FREE_NULL_MESSAGE /* does the user want a specific message? */ dmalloc_message("WARNING: tried to free(0) from '%s'", _dmalloc_chunk_desc_pnt(where_buf, sizeof(where_buf), file, line));#endif /* * NOTE: we have here both a default in the settings.h file and a * runtime token in case people want to turn it on or off at * runtime. */ if (BIT_IS_SET(_dmalloc_flags, DEBUG_ERROR_FREE_NULL)) { dmalloc_errno = ERROR_IS_NULL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -