📄 malloc.c
字号:
* is defined by your compiler. * * ARGUMENTS: * * pnt -> Existing pointer we are freeing. */#undef cfreeDMALLOC_FREE_RET cfree(DMALLOC_PNT pnt){ char *file; int ret; GET_RET_ADDR(file); ret = dmalloc_free(file, DMALLOC_DEFAULT_LINE, pnt, DMALLOC_FUNC_CFREE); #if (defined(__STDC__) && __STDC__ == 1) || defined(__cplusplus) || defined(STDC_HEADERS)#else return ret;#endif}/******************************* utility calls *******************************//* * int dmalloc_verify * * DESCRIPTION: * * Verify a pointer which has previously been allocated by the * library or check the entire heap. * * RETURNS: * * Success - MALLOC_VERIFY_NOERROR * * Failure - MALLOC_VERIFY_ERROR * * ARGUMENTS: * * pnt -> Pointer we are verifying. If 0L then check the entire heap. */int dmalloc_verify(const DMALLOC_PNT pnt){ int ret; if (! dmalloc_in(DMALLOC_DEFAULT_FILE, DMALLOC_DEFAULT_LINE, 0)) { return MALLOC_VERIFY_NOERROR; } /* should not check heap here because we will be doing it below */ if (pnt == NULL) { ret = _dmalloc_chunk_heap_check(); } else { ret = _dmalloc_chunk_pnt_check("dmalloc_verify", pnt, 1 /* exact pointer */, 0 /* no min size */); } dmalloc_out(); if (ret) { return MALLOC_VERIFY_NOERROR; } else { return MALLOC_VERIFY_ERROR; }}/* * int malloc_verify * * DESCRIPTION: * * Verify a pointer which has previously been allocated by the * library. Same as dmalloc_verify. * * RETURNS: * * Success - MALLOC_VERIFY_NOERROR * * Failure - MALLOC_VERIFY_ERROR * * ARGUMENTS: * * pnt -> Pointer we are verifying. If 0L then check the entire heap. */int malloc_verify(const DMALLOC_PNT pnt){ return dmalloc_verify(pnt);}/* * int dmalloc_verify_pnt * * DESCRIPTION: * * This function is mainly used by the arg_check.c functions to verify * specific pointers. This can be used by users to provide more fine * grained tests on pointers. * * RETURNS: * * Success - MALLOC_VERIFY_NOERROR * * Failure - MALLOC_VERIFY_ERROR * * ARGUMENTS: * * file -> File-name or return-address of the caller. You can use * __FILE__ for this argument or 0L for none. * * line -> Line-number of the caller. You can use __LINE__ for this * argument or 0 for none. * * func -> Function string which is checking the pointer. 0L if none. * * pnt -> Pointer we are checking. * * exact_b -> Set to 1 if this pointer was definitely handed back from * a memory allocation. If set to 0 then this pointer can be inside * another allocation or outside the heap altogether. * * min_size -> Make sure that pointer can hold at least that many * bytes if inside of the heap. If -1 then make sure it can handle * strlen(pnt) + 1 bytes (+1 for the \0). If 0 then don't check the * size. */int dmalloc_verify_pnt(const char *file, const int line, const char *func, const void *pnt, const int exact_b, const int min_size){ int ret; if (! dmalloc_in(file, line, 0)) { return MALLOC_VERIFY_NOERROR; } /* call the pnt checking chunk code */ ret = _dmalloc_chunk_pnt_check(func, pnt, exact_b, min_size); dmalloc_out(); if (ret) { return MALLOC_VERIFY_NOERROR; } else { return MALLOC_VERIFY_ERROR; }}/* * unsigned int dmalloc_debug * * DESCRIPTION: * * Set the global debug functionality flags. You can also use * dmalloc_debug_setup. * * Note: you cannot add or remove certain flags such as signal * handlers since they are setup at initialization time only. * * RETURNS: * * The old debug flag value. * * ARGUMENTS: * * flags -> Flag value to set. Pass in 0 to disable all debugging. */unsigned int dmalloc_debug(const unsigned int flags){ unsigned int old_flags; if (! enabled_b) { (void)dmalloc_startup(NULL /* no options string */); } old_flags = _dmalloc_flags; /* add the new flags */ _dmalloc_flags = flags; return old_flags;}/* * unsigned int dmalloc_debug_current * * DESCRIPTION: * * Returns the current debug functionality flags. This allows you to * save a dmalloc library state to be restored later. * * RETURNS: * * Current debug flags. * * ARGUMENTS: * * None. */unsigned int dmalloc_debug_current(void){ if (! enabled_b) { (void)dmalloc_startup(NULL /* no options string */); } /* should not check the heap here since we are dumping the debug variable */ return _dmalloc_flags;}/* * void dmalloc_debug_setup * * DESCRIPTION: * * Set the global debugging functionality as an option string. * Normally this would be pased in in the DMALLOC_OPTIONS * environmental variable. This is here to override the env or for * circumstances where modifying the environment is not possible or * does not apply such as servers or cgi-bin programs. * * RETURNS: * * None. * * ARGUMENTS: * * options_str -> Options string to set the library flags. */void dmalloc_debug_setup(const char *options_str){ if (! enabled_b) { (void)dmalloc_startup(options_str); /* if we just started up then we don't have to do anything else */ return; } /* we need to lock */ if (! dmalloc_in(NULL /* no file-name */, 0 /* no line-number */, 0 /* don't-check-heap */)) { return; } process_environ(options_str); dmalloc_out();}/* * int dmalloc_examine * * DESCRIPTION: * * Examine a pointer and pass back information on its allocation size * as well as the file and line-number where it was allocated. If the * file and line number is not available, then it will pass back the * allocation location's return-address if available. * * RETURNS: * * Success - DMALLOC_NOERROR * * Failure - DMALLOC_ERROR * * ARGUMENTS: * * pnt -> Pointer we are checking. * * user_size_p <- Pointer to a DMALLOC_SIZE type variable which, if * not NULL, will be set to the size of bytes from the pointer. * * total_size_p <- Poiner to a DMALLOC_SIZE type variable which, if * not NULL, will be set to the total size given for this allocation * including administrative overhead. * * file_p <- Pointer to a character pointer which, if not NULL, will * be set to the file where the pointer was allocated. * * line_p <- Pointer to an unsigned integer which, if not NULL, will * be set to the line-number where the pointer was allocated. * * ret_attr_p <- Pointer to a void pointer, if not NULL, will be set * to the return-address where the pointer was allocated. * * used_mark_p <- Poiner to an unsigned integer which, if not NULL, * will be set to the mark of when the pointer was last "used". This * could be when it was allocated, reallocated, or freed. * * seen_p <- Poiner to an unsigned long which, if not NULL, will be * set to the number of times that this pointer has been allocated, * realloced, or freed. */int dmalloc_examine(const DMALLOC_PNT pnt, DMALLOC_SIZE *user_size_p, DMALLOC_SIZE *total_size_p, char **file_p, unsigned int *line_p, DMALLOC_PNT *ret_attr_p, unsigned long *used_mark_p, unsigned long *seen_p){ int ret; unsigned int user_size_map, tot_size_map; unsigned long *loc_seen_p; /* * NOTE: we use the size maps because we use a unsigned int size * type internally but may use some size_t externally. */ /* need to check the heap here since we are geting info from it below */ if (! dmalloc_in(DMALLOC_DEFAULT_FILE, DMALLOC_DEFAULT_LINE, 1)) { return DMALLOC_ERROR; } /* NOTE: we do not need the alloc-size info */ ret = _dmalloc_chunk_read_info(pnt, "dmalloc_examine", &user_size_map, &tot_size_map, file_p, line_p, ret_attr_p, &loc_seen_p, used_mark_p, NULL, NULL); dmalloc_out(); if (ret) { SET_POINTER(user_size_p, user_size_map); SET_POINTER(total_size_p, tot_size_map); SET_POINTER(seen_p, *loc_seen_p); return DMALLOC_NOERROR; } else { return DMALLOC_ERROR; }}/* * void dmalloc_track * * DESCRIPTION: * * Register an allocation tracking function which will be called each * time an allocation occurs. * * RETURNS: * * None. * * ARGUMENTS: * * track_func -> Function to register as the tracking function. Set * to NULL to disable. */void dmalloc_track(const dmalloc_track_t track_func){ tracking_func = track_func;}/* * unsigned long dmalloc_mark * * DESCRIPTION: * * Return to the caller the current "mark" which can be used later by * dmalloc_log_changed to log the changed pointers since this point. * Multiple marks can be saved and used. * * This is also the iteration number and can be logged at the front of * each memory transaction in the logfile with the LOG_ITERATION * define in settings.h and can be logged with each pointer with the * LOG_PNT_ITERATION define in settings.h. * * RETURNS: * * Current mark value * * ARGUMENTS: * * None. */unsigned long dmalloc_mark(void){ if (! enabled_b) { (void)dmalloc_startup(NULL /* no options string */); } return _dmalloc_iter_c;}/* * unsigned long dmalloc_memory_allocated * * DESCRIPTION: * * Return the total number of bytes allocated by the program so far. * * RETURNS: * * Total number of bytes allocated by the program so far. * * ARGUMENTS: * * None. */unsigned long dmalloc_memory_allocated(void){ if (! enabled_b) { (void)dmalloc_startup(NULL /* no options string */); } return _dmalloc_alloc_total;}/* * unsigned int dmalloc_page_size * * DESCRIPTION: * * Get the page-size being used by dmalloc. * * RETURNS: * * Page size. * * ARGUMENTS: * * None. */unsigned int dmalloc_page_size(void){ if (! enabled_b) { (void)dmalloc_startup(NULL /* no options string */); } return BLOCK_SIZE;}/* * unsigned long dmalloc_count_changed * * DESCRIPTION: * * Count the changed memory bytes since a particular mark. * * RETURNS: * * Number of bytes since mark. * * ARGUMENTS: * * mark -> Sets the point from which to count the changed memory. You * can use dmalloc_mark to get the current mark value which can later * be passed in here. Pass in 0 to report on the unfreed memory since * the program started. * * not_freed_b -> Set to 1 to count the new pointers that are non-freed. * * free_b -> Set to 1 to count the new pointers that are freed. */unsigned long dmalloc_count_changed(const unsigned long mark, const int not_freed_b, const int free_b){ unsigned long mem_count; if (! dmalloc_in(DMALLOC_DEFAULT_FILE, DMALLOC_DEFAULT_LINE, 1)) { return 0; } if (! BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_TRANS)) { dmalloc_message("counting the unfreed memory since mark %lu", mark); } mem_count = _dmalloc_chunk_count_changed(mark, not_freed_b, free_b); dmalloc_out(); return mem_count;}/* * void dmalloc_log_status * * DESCRIPTION: * * Dump dmalloc statistics to logfile. * * RETURNS: * * None. * * ARGUMENTS: * * None. */void dmalloc_log_stats(void){ if (! dmalloc_in(DMALLOC_DEFAULT_FILE, DMALLOC_DEFAULT_LINE, 1)) { return; } _dmalloc_chunk_log_stats(); dmalloc_out();}/* * void dmalloc_log_unfreed * * DESCRIPTION: * * Dump unfreed-memory info to logfile. * * RETURNS: * * None. * * ARGUMENTS: * * None. */void dmalloc_log_unfreed(void){ if (! dmalloc_in(DMALLOC_DEFAULT_FILE, DMALLOC_DEFAULT_LINE, 1)) { return; } if (! BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_TRANS)) { dmalloc_message("dumping the unfreed pointers"); } /* * to log the non-free we are interested in the pointers currently * being used */ _dmalloc_chunk_log_changed(0, 1, 0,#if DUMP_UNFREED_SUMMARY_ONLY 0#else 1#endif ); dmalloc_out();}/* * void dmalloc_log_changed * * DESCRIPTION: * * Dump the pointers that have changed since a point in time. * * RETURNS: * * mark -> Sets the point to compare against. You can use * dmalloc_mark to get the current mark value which can later be * passed in here. Pass in 0 to log what has changed since the * program started. * * not_freed_b -> Set to 1 to log the new pointers that are non-freed. * * free_b -> Set to 1 to log the new pointers that are freed. * * details_b -> Set to 1 to dump the individual pointers that have * changed otherwise the summaries will be logged. */void dmalloc_log_changed(const unsigned long mark, const int not_freed_b, const int free_b, const int details_b){ if (! dmalloc_in(DMALLOC_DEFAULT_FILE, DMALLOC_DEFAULT_LINE, 1)) { return; } _dmalloc_chunk_log_changed(mark, not_freed_b, free_b, details_b); dmalloc_out();}/* * void dmalloc_vmessage * * DESCRIPTION: * * Message writer with vprintf like arguments which adds a line to the * dmalloc logfile. * * RETURNS: * * None. * * ARGUMENTS: * * format -> Printf-style format statement. * * args -> Already converted pointer to a stdarg list. */void dmalloc_vmessage(const char *format, va_list args){ _dmalloc_vmessage(format, args);}/* * void dmalloc_message * * DESCRIPTION: * * Message writer with printf like arguments which adds a line to the * dmalloc logfile. * * RETURNS: * * None. * * ARGUMENTS: * * format -> Printf-style format statement. * * ... -> Variable argument list. */void dmalloc_message(const char *format, ...) /* __attribute__ ((format (printf, 1, 2))) */{ va_list args; va_start(args, format); _dmalloc_vmessage(format, args); va_end(args);}/* * const char *dmalloc_strerror * * DESCRIPTION: * * Convert a dmalloc error code into its string equivalent. * * RETURNS: * * Success - String version of the error * * Failure - The string "unknown error" * * ARGUMENTS: * * error_num -> Error number we are converting. */const char *dmalloc_strerror(const int error_num){ error_str_t *err_p; /* should not dmalloc_in here because _dmalloc_error calls this */ for (err_p = error_list; err_p->es_error != 0; err_p++) { if (err_p->es_error == error_num) { return err_p->es_string; } } return INVALID_ERROR;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -