Memory_debug

VSS/RSS/PSS/USS

  • VSS:Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)。(reported as VSZ from ps) is the total accessible address space of a process.

  • RSS:Resident Set Size 实际使用物理内存(包含共享库占用的内存)。

    resident set size, the non-swapped physical memory that a task has used (in kilobytes). (alias rssize, rsz). RSS is the total memory actually held in RAM for a process.

    • It does not include memory that is swapped out.
    • It does include memory from shared libraries as long as the pages from those libraries are actually in memory.
    • It does include all stack and heap memory.
  • PSS:Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存),但是 PSS 并不是在所有的Linux系统中都有提供的,比如 ps 命令中就没有PSS值,而 Android 的dumpsys命令就可以看到进程的PSS值。

    adb shell dumpsys meminfo <pid>
    
  • USS:Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)

一般来说内存占用大小有如下规律:VSS >= RSS >= PSS >= USS

Overview of Android Memory Management

Manage Your App’s Memory

调查 RAM 使用情况

dumpsys meminfo

Private (Clean and Dirty) RAM

这是仅由您的进程使用的内存。这是您的应用进程销毁后系统可以回收的 RAM 容量。通常情况下,最重要的部分是Private Dirty RAM,它的开销最大,因为只有您的进程使用它,而且其内容仅存在于 RAM 中,所以无法通过分页机制映射到硬盘(因为 Android 不使用swap)。您进行的所有 Dalvik 和原生堆分配都将是私有脏 RAM;您与 Zygote 进程共享的 Dalvik 和原生分配则是共享脏 RAM(shared dirty RAM)。

Proportional Set Size (PSS)

这是对应用 RAM 占用情况的衡量,考虑了在进程之间共享 RAM 页的情况。您的进程独占的 RAM 页会直接计入其 PSS 值,而与其他进程共享的 RAM 页则仅会按相应比例计入 PSS 值。例如,两个进程之间共享的 RAM 页会将其一半的大小分别计入这两个进程的 PSS 中。

Dalvik Heap

应用中的 Dalvik 分配所占用的 RAM。Pss Total 包括所有 Zygote 分配(如上述 PSS 定义中所述,通过进程之间共享的内存容量来衡量)。Private Dirty 值是仅分配给您的应用堆的实际 RAM,包含了您自己的分配和任何 Zygote 分配页,这些分配页自从 Zygote 派生您的应用进程以来已被修改。

注意:在包含 Dalvik Other 区段的更高平台版本上,Dalvik 堆的 Pss Total 和 Private Dirty 数值不包括 Dalvik 开销(例如即时编译 (JIT) 和垃圾回收记录),而更低的版本会在 Dalvik 中将其一并列出。

.so mmap 和 .dex mmap

映射的 .so(原生)和 .dex(Dalvik 或 ART)代码占用的 RAM。Pss Total 值包括应用之间共享的平台代码;Private Clean 是您的应用自己的代码。通常,实际映射的内存容量要大得多。此处的 RAM 只是应用已执行的代码当前需要占用的 RAM。不过,.so mmap 具有较大容量的私有脏 RAM,这是因为在将其加载到最终地址时对原生代码进行了修复(However, the .so mmap has a large private dirty, which is due to fix-ups to the native code when it was loaded into its final address.)。

.oat mmap

这是代码映像占用的 RAM 容量,根据由多个应用共用的预加载类计算。此映像在所有应用之间共享,不受特定应用影响。

.art mmap

这是堆映像占用的 RAM 容量,根据由多个应用共用的预加载类计算。此映像在所有应用之间共享,不受特定应用影响。尽管 ART 映像包含 Object 实例,但它不会计入您的堆占用空间。

Unknown

系统无法将其分类到其他更具体的一个项中的任何 RAM 页。当前,此类 RAM 页主要包含原生分配,由于地址空间布局随机化 (ASLR),工具在收集此数据时无法识别这些分配。与 Dalvik 堆相同,Unknown 的 Pss Total 考虑了与 Zygote 共享的容量,且 Private Dirty 是仅由您的应用占用的未知 RAM。

TOTAL

您的进程占用的按比例分摊的内存大小 (PSS) RAM 总容量,等于上述所有 PSS 字段的总和。该值表示了您的进程占用的内存容量占总体内存容量的比重,可以直接与其他进程和可用的总 RAM 进行比较。

Private DirtyPrivate Clean 合起来就是您进程中的总分配,这些分配未与其他进程共享。这些分配(尤其是 Private Dirty)的容量等于进程销毁后将释放到系统中的 RAM 容量。脏 RAM 页由于已被修改过,因此必须保留在 RAM 中(因为没有交换);干净 RAM 页是从某个持久性文件(例如正在执行的代码)映射而来的,因此如果暂时不使用,可以将其换出 RAM。

ViewRootImpl

您的进程中当前处于活动状态的根视图数量。每个根视图都与一个窗口关联,因此该值有助于确定与对话框或其他窗口有关的内存泄漏。

AppContexts 和 Activities

您的进程中当前处于活动状态的应用 Context 和 Activity 对象数量。该值可以帮助您快速确定发生泄漏的 Activity 对象,这些对象由于存在对其的静态引用(比较常见)而无法进行垃圾回收。这些对象往往关联了许多其他分配,因此是查找大型内存泄漏的理想工具。

注意:View 或 Drawable 对象也会保留对其源 Activity 的引用,因此保留 View 或 Drawable 对象也会导致您的应用泄漏 Activity。

.Heap(仅带有 -d 标志)

这是应用堆所占用的内存容量,其中不包括映像中的对象和大型对象空间,但包括 zygote 空间和非移动空间。

.LOS(仅带有 -d 标志)

这是由 ART 大型对象空间占用的 RAM 容量,其中包括 zygote 大型对象。大型对象是所有大于 12KB 的原语数组分配。

.GC(仅带有 -d 标志)

这是垃圾回收的开销成本。没有什么办法能够真正减少这一开销。

.JITCache(仅带有 -d 标志)

这是 JIT 数据和代码缓存占用的内存容量。通常情况下,该值为 0,因为所有应用都会在安装时编译。

.Zygote(仅带有 -d 标志)

这是 zygote 空间占用的内存容量。zygote 空间在设备启动过程创建且永远不会被分配。

.NonMoving(仅带有 -d 标志)

这是由 ART 非移动空间占用的 RAM 容量。非移动空间包含特殊的不可移动对象,例如字段和方法。您可以通过在应用中减少使用字段和方法来减小这部分空间。

.IndirectRef(仅带有 -d 标志)

这是由 ART 间接引用表占用的 RAM 容量。通常此容量较小,但如果很高,可以通过减少使用的本地和全局 JNI 引用数量来减小此容量。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
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.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值