android+内存泄露补丁,android native 内存泄露检查(libc.debug.malloc )

转自:http://www.csdn123.com/html/blogs/20131011/81402.htm

Android对内存的使用包括内存泄漏和内存越界,内存泄漏会导致系统内存减少,最终分配不到内存,这样大的程序就不能运行,甚至系统没有内存而崩溃。Android中kernel和应用程序都可能会有内存泄漏和越界。对于Java代码,在越界的时候虚拟机会加以检查并抛出异常。而对于C/C++代码,越界的时候就悄无声息地让程序出错或crash

内核中已经内嵌了内存泄漏的代码,编译的时候需要打开配置

代码及帮助位置:

其中kmemcheck是检测内存越界等错误的,目前只支持X86

kernel/Documentation/kmemleak.txt

kernel/Documentation/kmemcheck.txt

kernel/mm/kmemleak.c

kernel/mm/kmemcheck.c

内核配置

CONFIG_DEBUG_KMEMLEAK=y

CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=1000

其中CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE的大小跟board的kernel porting相关,

有的不需要定义,有的需要定义大一点,可以在kmemleak.c中模块初始化代码中调试.

kmemleak模块初始化成功后,会产生/sys/kernel/debug/kmemleak这个文件

操作命令如下:

#su

#echo scan > /sys/kernel/debug/kmemleak扫描泄漏

#cat /sys/kernel/debug/kmemleak  查看泄漏

#echo clear > /sys/kernel/debug/kmemleak清除结果

当出现泄漏后,会有提示,比如

unreferenced object 0xd25f3cc0 (size 64):

comm "Binder_5", pid 1257, jiffies 68676 (age 3105.280s)

hex dump (first 32 bytes):

00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00  ................

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

backtrace:

[] create_object+0x12c/0x248

[] kmemleak_alloc+0x88/0xcc

[] kmem_cache_alloc_trace+0x13c/0x1f4

[] ion_carveout_heap_map_dma+0x34/0xcc

[] ion_alloc+0x170/0x3f0

[] ion_ioctl+0xc0/0x410

[] do_vfs_ioctl+0x4f4/0x568

[] sys_ioctl+0x48/0x6c

[] ret_fast_syscall+0x0/0x48

[] 0xffffffff

通过backtrace可以看到泄漏的地方是ion_carveout_heap_map_dma,通过看代码发现是

ion_carveout_heap_unmap_dma的时候少释放了内存。

kmemleak的原理这里不作介绍,大致原理扫描是否有指针指向这段内存,没有则认为是泄漏,这也导致有的地方会误报,比如内存重复使用带引用次数的,

int  offset = 4;

char *real = kmalloc(size, flag) + offset

kfree(real - offset)

在内核中这种特殊的地方很少,大部分检测出来的都是真的泄漏了。

参考: kernel/Documentation/vm/slub.txt

内核配置为使用slub作为内存分配器,slub本身提供了检查越界的接口,如果kernel刚启动就要检查内存破坏,则需要编译的时候配置CONFIG_SLUB_DEBUG_ON=y

否则可以使用slabinfo –d A来打开检查功能,打开后,slub会在内存后面加一些关键字,释放的时候会检查是否被破坏,如果破坏了,check_bytes_and_report中print一个警告,

可以修改check_bytes_and_report后面部分的代码,在debug版本中加入panic让系统死机来报告内存越界错误。

static int check_bytes_and_report(struct kmem_cache *s, struct page *page,

u8 *object, char *what,

u8 *start, unsigned int value, unsigned int bytes)

{

u8 *fault;

u8 *end;

fault = memchr_inv(start, value, bytes);

if (!fault)

return 1;

end = start + bytes;

while (end > fault && end[-1] == value)

end--;

slab_bug(s, "%s overwritten", what);

printk(KERN_WARN "INFO: 0x%p-0x%p. First byte 0x%x instead of 0x%x\n",

fault, end - 1, fault[0], value);

print_trailer(s, page, object);

restore_bytes(s, what, value, fault, end);

return 0;

}

比如显示如下:

BUG kmalloc-8: Redzone overwritten

--------------------------------------------------------------------

INFO: 0xc90f6d28-0xc90f6d2b. First byte 0x00 instead of 0xcc INFO: Slab 0xc528c530 flags=0x400000c3 inuse=61 fp=0xc90f6d58 INFO: Object 0xc90f6d20 @offset=3360 fp=0xc90f6d58 INFO: Allocated in get_modalias+0x61/0xf5 age=53 cpu=1 pid=554

Bytes b4 0xc90f6d10:  00 00 00 00 00 00 00 00 5a 5a 5a 5a 5a 5a 5a 5a ........ZZZZZZZZ Object 0xc90f6d20:  31 30 31 39 2e 30 30 35                         1019.005 Redzone 0xc90f6d28:  00 cc cc cc                                     . Padding 0xc90f6d50:  5a 5a 5a 5a 5a 5a 5a 5a                         ZZZZZZZZ

[] dump_trace+0x63/0x1eb

[] show_trace_log_lvl+0x1a/0x2f

[] show_trace+0x12/0x14

[] dump_stack+0x16/0x18

[] object_err+0x143/0x14b

[] check_object+0x66/0x234

[] __slab_free+0x239/0x384

[] kfree+0xa6/0xc6

[] get_modalias+0xb9/0xf5

[] dmi_dev_uevent+0x27/0x3c

[] dev_uevent+0x1ad/0x1da

[] kobject_uevent_env+0x20a/0x45b

[] kobject_uevent+0xa/0xf

[] store_uevent+0x4f/0x58

[] dev_attr_store+0x29/0x2f

[] sysfs_write_file+0x16e/0x19c

[] vfs_write+0xd1/0x15a

[] sys_write+0x3d/0x72

[] sysenter_past_esp+0x5f/0x99

[] 0xb7f7b410

可以使用ddms来查看系统的内存使用情况,是靠读取/proc/meminfo来分析出来的框图。

单个进程的内存使用情况可以检查proc//status

再具体可以看

/proc//statm

/proc//maps

/proc//smaps

top命令也可以显示VSS和RSS

VSS - Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)

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

PSS - Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)

USS - Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存

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

# procrank -h

Usage: procrank [ -W ] [ -v | -r | -p | -u | -h ]

-v  Sort by VSS.

-r  Sort by RSS.

-p  Sort by PSS.

-u  Sort by USS.

(Default sort order is PSS.)

-R  Reverse sort order (default is descending).

-w  Display statistics for working set only.

-W  Reset working set of all processes.

-h  Display this help screen.

And here is some sample output:

# procrank

PID      Vss      Rss      Pss      Uss  cmdline

1217   36848K   35648K   17983K   13956K  system_server

1276   32200K   32200K   14048K   10116K  android.process.acore

1189   26920K   26920K    9293K    5500K  zygote

1321   20328K   20328K    4743K    2344K  android.process.media

1356   20360K   20360K    4621K    2148K  com.android.email

1303   20184K   20184K    4381K    1724K  com.android.settings

1271   19888K   19888K    4297K    1764K  com.android.inputmethod.latin

1332   19560K   19560K    3993K    1620K  com.android.alarmclock

1187    5068K    5068K    2119K    1476K  /system/bin/mediaserver

1384     436K     436K     248K     236K  procrank

1     212K     212K     200K     200K  /init

753     572K     572K     171K     136K  /system/bin/rild

748     340K     340K     163K     152K  /system/bin/sh

751     388K     388K     156K     140K  /system/bin/vold

1215     148K     148K     136K     136K  /sbin/adbd

757     352K     352K     117K      92K  /system/bin/dbus-daemon

760     404K     404K     104K      80K  /system/bin/keystore

759     312K     312K     102K      88K  /system/bin/installd

749     288K     288K      96K      84K  /system/bin/servicemanager

752     244K     244K      71K      60K  /system/bin/debuggerd

详细解释见如下:

Android has a tool calledprocrank (/system/xbin/procrank), which lists out the memory usage of Linux processes in order from highest to lowest usage. The sizes reported per process are VSS, RSS, PSS, and USS.

For the sake of simplicity in this description, memory will be expressed in terms of pages, rather than bytes. Linux systems like ours manage memory in 4096 byte pages at the lowest level.

VSS (reported as VSZ from ps) isthe total accessible address space of a process. This size also includes memory that may not be resident in RAM like mallocs that have been allocated but not written to. VSS is of very little use for determing real memory usage of a process.

RSS is thetotal memory actually held in RAM for a process. RSS can be misleading, because it reports the total all of the shared libraries that the process uses, even though a shared library is only loaded into memory once regardless of how many processes use it. RSS is not an accurate representation of the memory usage for a single process.

PSS differs from RSS in that it reports the proportional size of its shared libraries, i.e. if three processes all use a shared library that has 30 pages, that library will only contribute 10 pages to the PSS that is reported for each of the three processes. PSS is a very useful number because when the PSS for all processes in the system are summed together, that is a good representation for the total memory usage in the system. When a process is killed, the shared libraries that contributed to its PSS will be proportionally distributed to the PSS totals for the remaining processes still using that library. In this way PSS can be slightly misleading, because when a process is killed, PSS does not accurately represent the memory returned to the overall system.

USS is the total private memory for a process, i.e. that memory that is completely unique to that process. USS is an extremely useful number because it indicates the true incremental cost of running a particular process. When a process is killed, the USS is the total memory that is actually returned to the system. USS is the best number to watch when initially suspicious of memory leaks in a process.

Dalvik Heap靠zygote预先加载了类和数据,当zygote fork一个android应用的时候,新的应用得到这个Heap的copy-on-write mapping

5.1.   JAVA的内存泄漏和越界

JAVA语言本身对内存越界是敏感的,JAVA中内存越界虚拟机抛出异常。

JAVA的内存泄漏的检测可以通过在eclipse中安装Memory Analyzer Tool(MAT)来插件来进行。

这里只简单说下步骤,需要完整的SDK和eclipse环境

1.打开Eclipse

2.选择Help->Install New Software;

(这个地址可能会变化,但是新的地址可以在官方网站上找到

http://www.eclipse.org/mat/downloads.php)

4.生成.Hprof文件:插入SD卡,在Eclipse中的DDMS中选择要测试的进程,然后点击

Update Heap和Dump HPROF file两个按钮。

.Hprof文件会自动保存在SD卡上

把.hprof文件拷贝到PC上的\ android-sdk-windows\tools目录下。这个由DDMS生成的

文件不能直接在MAT打开,需要转换。进入android-sdk-windows \tools所在目录,

并输入命令hprof-conv xxxxx.hprof yyyyy.hprof,其中xxxxx.hprof为原始文件,

yyyyy.hprof为转换过后的文件。

5..打开MAT:

在Eclipse中点击Windows->Open Perspective->Other->Memory Analysis

6.导入.hprof文件

在MAT中点击File->Open File打开刚刚转换而得到的yyyyy.hprof文件,并Cancel掉自

动生成报告,点击Dominator Tree,并按Package分组,选择自己所定义的Package类点右键,在弹出菜单中选择List objects->With incoming references。

这时会列出所有可疑类,右键点击某一项,并选择Path to GC Roots->exclude weak/soft references,会进一步筛选出跟程序相关的所有有内存泄露的类。据此,可以追踪到代码中的某一个产生泄露的类。

5.2.   Native的内存泄漏和越界

Android的native内存泄漏可以用valgrind工具,但是这个工具在android里运行太慢,Android里的bionic库提供了内存泄漏的检测方法

见bionic/libc/bionic/malloc_debug_common.c里的注释.

所有的native内存分配函数都在libc库里,为了跟踪,需要使用这个库的特别版版本libc_malloc_debug_leak.so和libc_malloc_debug_qemu.so,可以看看eng或这user-debug版中的/system/lib/下是否有这两个文件,其中libc_malloc_debug_qemu.so是模拟器用的。

在malloc_debug_common.c中的内存调试靠读取属性libc.debug.malloc来控制的,属性值含义如下:

libc.debug.malloc1    检测内存泄漏

libc.debug.malloc5    分配的内存用0xeb填充,释放的内存用0xef填充

libc.debug.malloc10  内存分配打pre-和post- 的桩子,可以检测内存的overruns

libc.debug.malloc20   SDK模拟器上检测内存用

简单的内存泄漏检测可以通过adb shell写为

#setprop libc.debug.malloc1

#stop

#start

然后logcat就可以显示内存泄漏,有的server可能stop杀不掉,为了开机就启动,可以在开机的时候就设置属性。

可以修改init.rc,增加setprop libc.debug.malloc10属性编译烧机,

或者

#adb remount

#vi system/build.prop增加libc.debug.malloc=10属性

除了通过logcat看,也可以配置ddms,通过ddms来看内存泄漏。

可以在~\.android\ddms.cfg文件后面添加native=true这样打开ddms就可以看到Native Heap了

点击snapshot current native heap usageke根据提示在symbol search path里输入相应库的符号表路径就行了,需要在启动ddms前把arm-linux-androideabi-addr2linux所在的路径加到PATH环境变量中,如果shell中已经运行过编译android前的. build/enxxx  lunch等操作,则已经加到PATH中去了。

找到泄漏后,根据提示的backtrace地址,可以用NDK中的arm-linux-androideabi-addr2line工具算出对应的函数地址,也可以排列成用tombstone的格式,用stacktrace工具求出函数调用关系。在上图ddms中,在symbol search path里填入编译是的库的路径,

可能可以直接显示出函数的名字。

在libc初始化的时候,注册了atexit函数(__libc_init函数),所以程序退出的时候会调用见native的内存泄漏在程序退出的时候会调用到malloc_debug_fini

void malloc_debug_fini(void)

{

/* We need to finalize malloc iff we implement here custom

* malloc routines (i.e. USE_DL_PREFIX is defined) for libc.so */

#if defined(USE_DL_PREFIX) && !defined(LIBC_STATIC)

if (pthread_once(&malloc_fini_once_ctl, malloc_fini_impl)) {

error_log("Unable to finalize malloc_debug component.");

}

#endif  // USE_DL_PREFIX && !LIBC_STATIC

}

对于mediaserver等进程,它一直不退出,就无法显示出泄漏的内存,用kill的方式也不能让atexit注册的退出函数得到调用,所以无法自动显示内存错误,针对server这种情况,有两种方式来处理,这两种方式也适用于其它的可以退出的进程。

第一种是在程序中加入检查泄漏的代码,通过调用get_malloc_leak_info()来查看是否总是不停地增长的。

第二种方法如下: server name为固定的一个server的名字(可以用service list查看)

1.     保存/proc//maps文件到PC机器

2.     ps

3.      dumpsys    -m >   1.mm

4.      操作手机

5.      dumpsys  -m >  2.mm

然后比较1.mm和2.mm,看看2比1多了那些内容

内容如下

size    31379, dup    1, 0x400f5dc8, 0x400ae2c6, 0x413afa96, 0x400ab020, 0x400aab74

其中size后面的数字表示分配的大小,dup分配的次数。

通过第1步中的maps文件,可以看到该进程每个库加载的起始地址

比如。0x413afa96是落在camera.sc8825.so的代码段内的,由此计算其指令在文件内的

偏移量,0x413afa96 - 0x41391000 = 0x1ea96。然后用addr2line就可以查看这条指

令对应的源码在哪个文件的哪个位置。

41391000-413e9000 r-xp 00000000 b3:0c

535        /system/lib/hw/camera.sc8825.so

$ arm-linux-androideabi-addr2line -e

out/target/product/sp8825ea/symbols/system/lib/hw/camera.sc8825.so 0x1ea96

如果是应用这则要用dumpheap命令

am dumpheap -n  /data/1.mm

am dumpheap -n  /data/2.mm

上面addr2line的过程可以用脚本去自动实现

也可以随时调用dumpsys meminfo $package_name or $pid看看消耗内存的趋势

在stop之后,可以用ps看看哪些server还是没被杀掉,这样的server要调试的要需要主动kill掉,然后再start才可以,或者在开机的时候就设置属性libc_debug_malloc为1

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、付费专栏及课程。

余额充值