关键词 > C语言代写

Exercise 4

发布时间:2023-04-21

Hello, dear friend, you can consult us at any time if you have any questions, add WeChat: daixieit

Exercise 4

Due:  See website for due date.

What to submit:  See website.

The theme of this exercise is automatic memory management, leak detection and virtual memory.

1. Understanding valgrind’s leak checker

Valgrind is a tool that can aid in nding memory leaks in C programs. To that end, it per- forms an analysis similar to the mark” phase of a traditional mark-and-sweep garbage collector right before a program exits and identifies still reachable objects and leaks.

For leaks, it uses the definition prevalent in C: objects that have been allocated but not yet freed, and there is no possible way for a legal program to access them in the future.

Read Section 4.2.8 Memory leak detection in the Valgrind Manual [URL] and construct a C program leak .c that, when run with

valgrind  --leak-check=full  --show-leak-kinds=all  ./leak

produces the following output:

==2717145== Memcheck, a memory error detector

==2717145== Copyright (C) 2002-2022, and GNU GPL’d, by Julian Seward et al.

==2717145== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info

==2717145== Command: ./leak

==2717145==

==2717145==

==2717145== HEAP SUMMARY:

==2717145== in use at exit: 1,450 bytes in 4 blocks

==2717145== total heap usage: 4 allocs, 0 frees, 1,450 bytes allocated

==2717145==

==2717145== 300 bytes in 1 blocks are still reachable in loss record 1 of 4

==2717145== at 0x4C38135: malloc (vg_replace_malloc.c:381)

==2717145== by 0x4005A8: main (leak.c:12)

==2717145==

==2717145== 400 bytes in 1 blocks are indirectly lost in loss record 2 of 4

==2717145== at 0x4C38135: malloc (vg_replace_malloc.c:381)

==2717145== by 0x4005C7: main (leak.c:15)

==2717145==

==2717145== 500 bytes in 1 blocks are indirectly lost in loss record 3 of 4

==2717145== at 0x4C38135: malloc (vg_replace_malloc.c:381)

==2717145== by 0x4005E4: main (leak.c:16)

==2717145==

==2717145== 1,150 (250 direct, 900 indirect) bytes in 1 blocks are definitely lost in loss record 4 of 4

==2717145== at 0x4C38135: malloc (vg_replace_malloc.c:381)

==2717145== by 0x4005B9: main (leak.c:14)

==2717145==

==2717145== LEAK SUMMARY:

==2717145== definitely lost: 250 bytes in 1 blocks

==2717145== indirectly lost: 900 bytes in 2 blocks

==2717145== possibly lost: 0 bytes in 0 blocks

==2717145== still reachable: 300 bytes in 1 blocks

==2717145== suppressed: 0 bytes in 0 blocks

==2717145==

==2717145== For lists of detected and suppressed errors, rerun with: -s

==2717145== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

(the line numbers need not match, but the LEAK summary should.)

2. Reverse Engineering A Memory Leak

In this part of the exercise, you will be given a post-mortem dump of a JVM’s heap that was obtained when running a program with a memory leak. The dump was produced at the point in time when the program ran out of memory because its live heap size exceeded the maximum, which can be accomplished as shown in this log:

$ java -XX:+HeapDumpOnOutOfMemoryError -Xmx64m OOM

java .lang .OutOfMemoryError: Java heap space

Dumping heap to java_pid2709418 .hprof . . .

Heap dump file created [67868449 bytes in 0 . 065 secs]

Exception in thread "main" java .lang .OutOfMemoryError: Java heap space

at OOM$BCData.<init>(OOM.java:7 )

at OOM.main(OOM.java:18 )

Your task is to examine the heap dump (oom.hprof) and reverse engineer the leaky pro- gram.

To that end, you must install the Eclipse Memory Analyzer on your computer. It can be downloaded from this URL. Open the heap dump.

Requirements

● Your program must run out of memory when run as shown above.  You should double-check that the created heap dump matches the provided dump, where “matches” is defined as follows.

The structure of the reachability graph of the subcomponent with the largest re- tained size should be similar in your heap dump as in the provided heap dump. (Other information such as the content of arrays may differ.)

You will need to write one or more classes and write code that allocates these objects and creates references between them. You should choose the same eld and class names in your program as in the heap dump, and no extra ones (we will check this). Think of eld names as edge labels in the reachability graph.

You should investigate whether classes from Java’s standard library are involved in the leak.

Hints

The program that was used to create the heap dump is 19 lines long (without com- ments, and including the main function), though your line numbers may differ.

Static inner classes are separated with a dollar sign $. For instance, A$B is the name of a static inner class called B nested in A. (Your solution should use the same class names as in the heap dump.)

Start with the Leak Suspects” report, then look in Details.  Use the List Objects ... with outgoing references” feature to nd a visualization of the objects that were part of the heap when the program ran out of memory.

The dominator tree” option can also give you insight into the structure of the object graph. Zoom in on the objects that have the largest Retained Heap” quantity.

Use the Java Tutor website to write small test programs and trace how the reacha- bility graph changes over time.

Do not forget the -Xmx64m switch when running your program, or else your pro- gram may run for several minutes before running out of memory, even if imple- mented correctly.

● Do not access the oom .hprof file through a remote le system path such as a mapped Google drive or similar. Students in the past have reported runtime errors in Eclipse MAT when trying to do that. Instead, copy it to your local computer’s le system first as a binary le. The SHA256 sum of oom .hprof is

40501a377a8ed221d36aa59649d56eab39cfed726f937b806a331ac497adcb76

3. Using mmap to list the entries in a ZIP file

Write a short program zipdir that displays the list of entries inside a zip le whose name is passed to the program as its rst argument. For each entry it should also print its com- pression ratio as a percentage rounded to the nearest tenth of a percent. The compression ratio is defined as the ratio of the compressed size to the uncompressed size. A sample use would be:

$  ./zipdir  heap . zip

heap1 .dot 41 . 9%

heap1 .in 66 .0%

heap1 .out 100 .0%

heap1 .png 89 .4%

heap2 .dot 36 .8%

heap2 .in 59 .5%

heap2 .out 100 .0%

heap2 .png 92 .5%

heap3 .dot 37 .0%

heap3 .in 59 .2%

heap3 .out 100 .0%

heap3 .png 92 .0%

Your program should use only the open(2), fstat(2), and mmap(2) system calls (plus any system calls needed to output the result, such as write(1) via printf.

Do not use read(2) (or higher-level functions such as fread(3), etc. that call read() internally).

The  ZIP le  format  is  described,   among  other  places,   on  the  WikiPedia  page

https://en.wikipedia.org/wiki/ZIP_(file_format)

Use the following algorithm:

open the le with open(2) in read-only mode.

use fstat(2) to determine the length of the le.

use mmap(2) to map the entire le into memory in a read-only way.

scan from the back of the le until you nd the beginning marker of the End of Central Directory Record (EOCD).

extract the number of central directory records in this zip archive and the start offset of the central directory.

Then, starting from the start offset of the central directory, examine each central directory le header and output the lename contained in it, along with the com- pression ratio. (Hint: use the following format string for printf:

printf   ("%-25 .*s  %5 .1f%%\n",  namelength,  name,  ratio);

Skip forward to the next central directory record by advancing 46 + m + n + k bytes where n is the length of the lename, m is the extra eld length, and k is the file comment length contained in each central le directory header.

Simplifying assumptions/hints:

All multibyte integers in a ZIP le are stored in little-endian order, and for the purposes of this exercise you may assume that the host byte order of the machine on which your program runs is little endian as well.

You may use pointer arithmetic on void  * pointers, which uses a stride of 1 byte (i.e., it assumes that sizeof(void)==1.   To access 16-bit or 32-bit values, use uint16_t  * and uint32_t  *, respectively under the assumption of little endian host byte order.

If the given file is not a well-formed ZIP archive then the behavior of your program can be undefined.