Differences

This shows you the differences between two versions of the page.

Link to this comparison view

ep:labs:04:contents:tasks:ex1 [2025/02/11 23:36]
cezar.craciunoiu
ep:labs:04:contents:tasks:ex1 [2026/03/24 12:23] (current)
radu.mantu
Line 1: Line 1:
-==== 01. [10p] Memory usage ====+==== 01. [10p] Valgrind ​====
  
-Open {{:​ep:​labs:​ep2017_l2_ex02.txt|ex01.py}} ​and take look at the codeWhat is the difference between the methods //​do_append()//​ and //​do_allocate()//? ​+Dynamic analysis tools can observe a running process and report memory-related 
 +issues that static analysis would miss entirelyIn this exercise you will use 
 +**Valgrind** to detect memory leaks in a small C program -- and get first taste 
 +of the dynamic instrumentation concept that will be developed further in Task 04 
 +with Intel Pin.
  
-Use //vmstat// to monitor the memory usage while performing the following experiments. In the main method, call: +=== [5p] Task A - Writing a leaky program ===
-  * The //​do_append//​ method on it's own (see //​Experiment 1//). +
-  * The //​do_allocate//​ method on it's own (see //​Experiment 2//). +
-  * Both methods as shown in the //​Experiment 3// area in the code. +
-  * Both methods as shown in the //​Experiment 4// area in the code.+
  
-Offer an interpretation for the obtained results ​and change the code in //​do_append()//​ so that the memory usage will be the same when performing //​Experiment 3// or //​Experiment 4//. \\+Read the contents of ''​leak.c'' ​and compile it: 
 +<code bash> 
 +$ gcc -g -o leak leak.c 
 +</code>
  
-HINTS: Python GC; Reference cycle+The **-g** flag includes debug symbols so Valgrind can report exact file names 
 +and line numbers.
  
-<solution -hidden+Now run it normally and observe that nothing seems wrong from the outside: 
-  * **Experiment 1,2:** There is not much difference in terms of memory usage between Experiment 1 and 2+<code bash
-  * **Experiment 3:** The //​do_append//​ method starts using memory. After it finished running, since there is no reference for the generated array, the allocated memory is unallocated (reference counting garbage collector). Then the next method, //​do_allocate//,​ starts running and using memory. +./leak 
-  * **Experiment 4:** After the first method ends, since in this case there is a reference for the generated array, the memory is not unallocated. When the second method starts running, the amount of memory that it uses is added to the amount already used by the first method. If the used memory is taking up almost all the available free memory of the system, you can notice: swpd increasing, buff decreasing, cache decreasing, and si, so, bi, bo activity.+$ echo "exit code$?" 
 +</code>
  
-Notice the increased number of interrupts and context switches. These are caused by time.sleep().+=== [5p] Task B - Detecting leaks with Valgrind ===
  
-</solution>+Run the same binary under Valgrind'​s memory error detector: 
 +<code bash> 
 +$ valgrind --leak-check=full --show-leak-kinds=all ./leak 
 +</code> 
 + 
 +Examine the output and answer the following questions:​ 
 +  - How many bytes are reported as **definitely lost**? Does this match what you would expect from reading the source? 
 +  - What is the difference between **definitely lost** and **indirectly lost** in Valgrind'​s terminology?​ 
 +  - At what line number does Valgrind point as the origin of the leak? Why is that line significant rather than the line where the pointer goes out of scope? 
 +  - Re-compile **without** the ''​-g''​ flag and run Valgrind again. What information is now missing from the report, and why?
  
 <​solution -hidden> <​solution -hidden>
-<code python>​ +  - 10 calls × 256 bytes **2560 bytes** definitely lost. 
-def do_append(size):​ +  ​- **Definitely lost**: the last pointer to the allocation is gone -- the memory 
-  result ​[] +    can never be freed**Indirectly lost**: memory reachable only through another 
-  ​result.append(result+    leaked block (e.g. a node in a leaked linked list). 
-  ​for i in range(size)+  ​- Valgrind points to the ''​malloc()''​ call inside ''​leaky_function()''​ because 
-    message= "some unique object %d" % i, * 1000 +    ​that is where the allocation originatedThe pointer going out of scope is a 
-    ​result.append(message) +    ​C concept; Valgrind tracks allocations at the heap level, not variable lifetimes
-    ​time.sleep(0.0001) +  ​- Without ''​-g'',​ Valgrind shows raw addresses and shared library offsets instead 
-  ​return result +    of ''​leak.c:​5''​. The source file name and line number come from the DWARF debug 
-</​code>​+    information embedded by the compiler.
 </​solution>​ </​solution>​
 +
 +<note tip>
 +**Troubleshooting**
 +-----
 +On certain distributions such as CachyOS, you may get the following error:
 +<​code>​
 +valgrind: ​ Fatal error at startup: a function redirection
 +valgrind: ​ which is mandatory for this platform-tool combination
 +valgrind: ​ cannot be set up.  Details of the redirection are:
 +</​code>​
 +**valgrind** need the DWARF debug info for **libc** in order to function properly. If the ELF file itself doesn'​t have it, **valgrind** will try to use [[https://​man.archlinux.org/​man/​debuginfod-find.1|debuginfod find]] to download it using the **Build ID** stored in the ''​.note.gnu.build-id''​ section. If the **debuginfod** server doesn'​t have it either, your only hope of getting it to work is:
 +  * recompiling **glibc** with debug symbols (out of the question)
 +  * starting a docker container with Ubuntu, Debian, Arch Linux, etc.
 +</​note>​
ep/labs/04/contents/tasks/ex1.1739309785.txt.gz · Last modified: 2025/02/11 23:36 by cezar.craciunoiu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0