Android malloc debug介绍

e4b02b457000275253746a770ecbd702.gif

和你一起终身学习,这里是程序员Android

经典好文推荐,通过阅读本文,您将收获以下知识点:

一 简述

android 的libc中有malloc_debug的hook调用,我们可以使用malloc_debug中的hook函数对内存分配进行跟踪加测。
malloc_debug主要包含的功能如下:

  1. 内存分配和释放跟踪,支持的函数如下:
malloc
    free
    calloc
    realloc
    posix_memalign
    memalign
    aligned_alloc
    malloc_usable_size

2) 支持内存边界,可以在申请的内存头部和尾部添加guard,内存越界检查,use after free,内存崩溃检查等。
3) 调用栈跟踪和打印,跟踪内存分配的同时保存内存分配的调用栈,方便内存泄漏检查。

二 malloc_debug使用

1) 开启malloc_debug
adb shell setprop libc.debug.malloc.program

  1. 设置相关检测项
    adb shell setprop libc.debug.malloc.options backtrace
Introduction The usual implementation of malloc and free are unforgiving to errors in their callers' code, including cases where the programmer overflows an array, forgets to free memory, or frees a memory block twice. This often does not affect the program immediately, waiting until the corrupted memory is used later (in the case of overwrites) or gradually accumulating allocated but unused blocks. Thus, debugging can be extremely difficult. In this assignment, you will write a wrapper for the malloc package that will catch errors in the code that calls malloc and free. The skills you will have learned upon the completion of this exercise are pointer arithmetic and a greater understanding of the consequences of subtle memory mistakes. Logistics Unzip debugging_malloc.zip into an empty directory. The files contained are as follows: File(s): Function: debugmalloc.c Contains the implementation of the three functions you will be writing. This is the one file you will be editing and handing in. debugmalloc.h Contains the declaration of the functions, as well as the macros that will call them. driver.c Contains main procedure and the code that will be calling the functions in the malloc package dmhelper.c, dmhelper.h Contain the helper functions and macros that you will be calling from your code grader.pl Perl script that runs your code for the various test cases and gives you feedback based on your current code debugmalloc.dsp Exercise 3 project file debugmalloc.dsw Exercise 3 workspace file tailor.h, getopt.c, getopt.h Tools that are used only by the driver program for I/O purposes. You will not need to know what the code in these files do. Others Required by Visual C++. You do not need to understand their purpose Specification Programs that use this package will call the macros MALLOC and FREE. MALLOC and FREE are used exactly the same way as the malloc() and free() functions in the standard C malloc package. That is, the line void *ptr = MALLOC ( n ) ;will allocate a payload of at least n bytes, and ptr will point to the front of this block. The line FREE(ptr);will cause the payload pointed to by ptr to be deallocated and become available for later use. The macros are defined as follows: #define MALLOC(s) MyMalloc(s, __FILE__, __LINE__) #define FREE(p) MyFree(p, __FILE__, __LINE__) The __FILE__ macro resolves to the filename and __LINE__ resolves to the current line number. The debugmalloc.c file contains three functions that you are required to implement, as shown: void *MyMalloc(size_t size, char *filename, int linenumber); void MyFree(void *ptr, char *filename, int linenumber); int AllocatedSize(); Using the macros above allow MyMalloc and MyFree to be called with the filename and line number of the actual MALLOC and FREE calls, while retaining the same form as the usual malloc package. By default, MyMalloc and MyFree() simply call malloc() and free(), respectively, and return immediately. AllocatedSize() should return the number of bytes currently allocated by the user: the sum of the requested bytes through MALLOC minus the bytes freed using FREE. By default, it simply returns 0 and thus is unimplemented. The definitions are shown below: void *MyMalloc(size_t size, char *filename, int linenumber) { return (malloc(size)); } void MyFree(void *ptr, char *filename, int linenumber) { free(ptr); } int AllocatedSize() { return 0; } Your job is to modify these functions so that they will catch a number of errors that will be described in the next section. There are also two optional functions in the debugmalloc.c file that you can implement: void PrintAllocatedBlocks(); int HeapCheck(); PrintAllocatedBlocks should print out information about all currently allocated blocks. HeapCheck should check all the blocks for possible memory overwrites. Implementation Details To catch the errors, you will allocate a slightly larger amount of space and insert a header and a footer around the "requested payload". MyMalloc() will insert information into this area, and MyFree() will check to see if the information has not changed. The organization of the complete memory block is as shown below: Header Checksum ... Fence Payload Footer Fence Note:MyMalloc() returns a pointer to the payload, not the beginning of the whole block. Also, the ptr parameter passed into MyFree(void *ptr) will point to the payload, not the beginning of the block. Information that you might want to store in this extra (header, footer) area include: a "fence" immediately around the requested payload with a known value like 0xCCDEADCC, so that you can check if it has been changed when the block is freed. the size of the block a checksum for the header to ensure that it has not been corrupted (A checksum of a sequence of bits is calculated by counting the number of "1" bits in the stream. For example, the checksum for "1000100010001000" is 4. It is a simple error detection mechanism.) the filename and line number of the MALLOC() call The errors that can occur are: Error #1: Writing past the beginning of the user's block (through the fence) Error #2: Writing past the end of the user's block (through the fence) Error #3: Corrupting the header information Error #4: Attempting to free an unallocated or already-freed block Error #5: Memory leak detection (user can use ALLOCATEDSIZE to check for leaks at the end of the program) To report the first four errors, call one of these two functions: void error(int errorcode, char *filename, int linenumber); errorcode is the number assigned to the error as stated above. filename and linenumber contain the filename and line number of the line (the free call) in which the error is invoked. For example, call error(2, filename, linenumber) if you come across a situation where the footer fence has been changed. void errorfl(int errorcode, char *filename_malloc, int linenumber_malloc, char *filename_free, int linenumber_free); This is the same as the error(), except there are two sets of filenames and line numbers, one for the statement in which the block was malloc'd, and the other for the statement in which the block was free'd (and the error was invoked). The fact that MyMalloc() and MyFree() are given the filename and line number of the MALLOC() and FREE() call can prove to be very useful when you are reporting errors. The more information you print out, the easier it will be for the programmer to locate the error. Use errorfl() instead of error() whenever possible. errorfl() obviously cannot be used on situations where FREE() is called on an unallocated block, since it was not ever MALLOC'd. Note: You will only be reporting errors from MyFree(). None of the errors can be caught in MyMalloc() In the case of memory leaks, the driver program will call AllocatedSize(), and the grader will look at its return value and possible output. AllocatedSize() should return the number of bytes currently allocated from MALLOC and FREE calls. For example, the code segment: void *ptr1 = MALLOC(10), *ptr2 = MALLOC(8); FREE(ptr2); printf("%d\n", AllocatedSize()); should print out "10". Once you have gotten to the point where you can catch all of the errors, you can go an optional step further and create a global list of allocated blocks. This will allow you to perform analysis of memory leaks and currently allocated memory. You can implement the void PrintAllocatedBlocks() function, which prints out the filename and line number where all currently allocated blocks were MALLOC()'d. A macro is provided for you to use to print out information about a single block in a readable and gradeable format: PRINTBLOCK(int size, char *filename, int linenumber) Also, you can implement the int HeapCheck() function. This should check all of the currently allocated blocks and return -1 if there is an error and 0 if all blocks are valid. In addition, it should print out the information about all of the corrupted blocks, using the macro #define PRINTERROR(int errorcode, char *filename, int linenumber), with errorcode equal to the error number (according to the list described earlier) the block has gone through. You may find that this global list can also allow you to be more specific in your error messages, as it is otherwise difficult to determine the difference between an overwrite of a non-payload area and an attempted FREE() of an unallocated block. Evaluation You are given 7 test cases to work with, plus 1 extra for testing a global list. You can type "debugmalloc -t n" to run the n-th test. You can see the code that is being run in driver.c. If you have Perl installed on your machine, use grader.pl to run all the tests and print out a table of results. There are a total of 100 possible points. Here is a rundown of the test cases and desired output (do not worry about the path of the filename): Test case #1 Code char *str = (char *) MALLOC(12); strcpy(str, "123456789"); FREE(str); printf("Size: %d\n", AllocatedSize()); PrintAllocatedBlocks(); Error # None Correct Output Size: 0 Points worth 10 Details 10 points for not reporting an error and returning 0 in AllocatedSize() Test case #2 Code char *str = (char *) MALLOC(8); strcpy(str, "12345678"); FREE(str); Error # 2 Correct Output Error: Ending edge of the payload has been overwritten. in block allocated at driver.c, line 21 and freed at driver.c, line 23 Points worth 15 Details 6 pts for catching error 3 pts for printing the filename/line numbers 6 pts for correct error message Test case #3 Code char *str = (char *) MALLOC(2); strcpy(str, "12"); FREE(str); Error # 2 Correct Output Error: Ending edge of the payload has been overwritten. in block allocated at driver.c, line 28 and freed at driver.c, line 30 Points worth 15 Details 6 pts for catching error 3 pts for printing the filename/line numbers 6 pts for correct error message Test case #4 Code void *ptr = MALLOC(4); *ptr2 = MALLOC(6); FREE(ptr); printf("Size: %d\n", AllocatedSize()); PrintAllocatedBlocks(); Error # None Correct Output Size: 6 Currently allocated blocks: 6 bytes, created at driver.c, line 34 Points worth 15 Details 15 pts for not reporting an error and returning 6 from AllocatedSize Extra for printing out the extra block Test case #5 Code void *ptr = MALLOC(4); FREE(ptr); FREE(ptr); Error # 4 Correct Output Error: Attempting to free an unallocated block. in block freed at driver.c, line 43 Points worth 15 Details 15 pts for catching error Extra for correct error message Test case #6 Code char *ptr = (char *) MALLOC(4); *((int *) (ptr - 8)) = 8 + (1 << 31); FREE(ptr); Error # 1 or 3 Correct Output Error: Header has been corrupted.or Error: Starting edge of the payload has been overwritten. in block allocated at driver.c, line 47 and freed at driver.c, line 49 Points worth 15 Details 9 pts for catching error 6 pts for a correct error message Test case #7 Code char ptr[5]; FREE(ptr); Error # 4 Correct Output Error: Attempting to free an unallocated block. in block freed at driver.c, line 54 Points worth 15 Details 15 pts for recognizing error Extra for printing correct error message Test case #8 (Optional) Code int i; int *intptr = (int *) MALLOC(6); char *str = (char *) MALLOC(12); for(i = 0; i < 6; i++) { intptr[i] = i; } if (HeapCheck() == -1) { printf("\nCaught Errors\n"); } Error # None Correct Output Error: Ending edge of the payload has been overwritten. Invalid block created at driver.c, line 59 Caught Errors Points worth Extra Details "Caught Errors" indicates that the HeapCheck() function worked correctly. Extra points possible. Your instructor may give you extra credit for implementing a global list and the PrintAllocatedBlocks() and HeapCheck() functions.
<think>嗯,用户想了解如何使用malloc_debug工具进行调试和内存管理。我需要根据提供的引用内容来组织回答。首先,用户之前可能问过相关问题,但根据当前的信息,我需要整理出步骤和关键点。 首先,我应该介绍malloc_debug的基本功能,比如检测内存泄漏、越界访问等,引用里的资料提到这些。然后,启用方法可能分不同的Android版本,比如Android 7.0前后,用户可能需要知道如何配置环境变量,比如libc.debug.malloc.options和libc.debug.malloc.program。这部分引用4里有提到,需要详细说明。 接下来,使用步骤可能包括配置属性、重启应用、分析日志。需要提到如何通过adb命令设置属性,以及如何抓取logcat日志。可能还要提到不同的选项,比如leak_track、guard等,引用2和4中有说明。 然后,常见问题检测部分应该分点,比如内存泄漏、越界访问、重复释放、未初始化使用。每个问题对应malloc_debug的检测方法,比如填充模式或guard区域,引用4中的细节可以用在这里。 最后,注意事项部分要提醒性能影响和Android版本差异,引用2提到不同版本的文档位置,可能需要用户查看对应的README文件。另外,示例部分可以给出一个简单的代码例子,说明如何启用并观察输出,引用3中的代码可能相关,但用户的问题更偏向工具使用而非代码实现。 需要确保回答结构清晰,分步骤,每个部分有引用标注。还要检查是否所有信息都来自提供的引用,避免添加外部知识。用户可能需要具体的命令行示例,比如adb命令,所以应该包含这些内容。另外,用户是Android应用工程师,可能需要针对APP的调试方法,引用4最后提到这点,所以启用方法要针对APP的情况,比如设置wrap属性或者使用adb shell setprop。</think>### malloc_debug工具使用方法 #### 一、工具功能概述 malloc_debugAndroid平台用于检测Native内存问题的工具,支持以下检测能力: 1. **内存泄漏检测**:追踪未释放的内存块并记录调用堆栈[^4] 2. **越界访问检测**:通过前后guard区域的填充模式(0xaa/0bb)识别越界写入[^4] 3. **重复释放检测**:记录已释放内存块的元数据,捕获二次free操作[^4] 4. **未初始化使用检测**:通过特定bit填充模式发现非法内存访问[^4] #### 二、启用步骤(以Android 7.0+为例) 1. **配置调试参数** ```bash # 设置调试选项(多个选项用|分隔) adb shell setprop libc.debug.malloc.options "verbose leak_track guard" # 指定目标应用包名 adb shell setprop libc.debug.malloc.program com.example.app # 对目标进程启用shim层 adb shell setprop wrap.com.example.app '"LIBC_DEBUG_MALLOC_OPTIONS=verbose leak_track"' ``` 2. **重启应用进程** ```bash adb shell am force-stop com.example.app ``` 3. **抓取调试日志** ```bash adb logcat -s "malloc_debug" ``` #### 三、关键调试选项说明 | 选项 | 功能描述 | 检测场景 | |------------|-----------------------------------|-----------------------| | `leak_track` | 记录内存分配堆栈 | 内存泄漏分析 | | `guard` | 启用前后保护区域(默认32字节) | 缓冲区溢出/下溢 | | `fill` | 分配时填充0xaa,释放时填充0xbb | 野指针/未初始化使用 | | `backtrace` | 记录完整调用堆栈(需符号表) | 定位问题代码位置 | #### 四、常见问题检测示例 1. **内存泄漏检测** 当应用退出时,日志会显示未释放的内存块信息: ``` malloc_debug: +++ MEMORY_LEAKS DETECTED +++ malloc_debug: 16 bytes leaked at 0x7a8f4c2000 (malloc from: main_thread+0x1234) ``` 2. **越界访问检测** 检测到guard区域被修改时会触发错误: ``` malloc_debug: +++ ALLOCATION 0x789acd0000 HAS CORRUPTED FRONT GUARD BYTES +++ ``` 3. **重复释放检测** 对已释放内存二次操作会立即报错: ``` malloc_debug: +++ DOUBLE FREE (free from: pthread_create+0x5678) ``` #### 五、注意事项 1. 调试模式下**性能下降明显**,建议仅在测试环境使用[^4] 2. Android N(7.0)前后版本配置方法不同,需参考对应版本文档[^2] 3. 完整功能列表可查看源码文档: ```bash # Android 7.0+文档路径 /bionic/libc/malloc_debug/README.md ``` #### 六、调试示例(C代码) 以下代码运行时会触发越界检测: ```c int* arr = malloc(10 * sizeof(int)); arr[10] = 42; // 越界写入触发guard检测 free(arr); ``` 对应日志输出: ``` malloc_debug: +++ ALLOCATION 0x7f9b1c2000 HAS CORRUPTED REAR GUARD BYTES +++ ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员Android

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值