{"id":8314,"date":"2023-03-13T11:31:40","date_gmt":"2023-03-13T09:31:40","guid":{"rendered":"https:\/\/blue.pri.ee\/ttu\/?p=8314"},"modified":"2026-03-22T20:51:44","modified_gmt":"2026-03-22T18:51:44","slug":"pr2en7-dynamic-memory-allocation","status":"publish","type":"post","link":"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en7-dynamic-memory-allocation\/","title":{"rendered":"PR2EN7: Dynamic memory allocation"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_85 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en7-dynamic-memory-allocation\/#Lab_materials\" >Lab materials<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en7-dynamic-memory-allocation\/#Lab_tasks\" >Lab tasks<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en7-dynamic-memory-allocation\/#Task_1_W07-1_Random_data_file_generator\" >Task 1 [W07-1]: Random data file generator<\/a><ul class='ez-toc-list-level-5' ><li class='ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en7-dynamic-memory-allocation\/#Requirements\" >Requirements<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en7-dynamic-memory-allocation\/#Workflow\" >Workflow<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en7-dynamic-memory-allocation\/#Qsort_comparison_function\" >Qsort comparison function<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en7-dynamic-memory-allocation\/#Testing\" >Testing<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en7-dynamic-memory-allocation\/#Extra_task_1_W07-2_Output_file_formats\" >Extra task 1 [W07-2]: Output file formats<\/a><ul class='ez-toc-list-level-5' ><li class='ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en7-dynamic-memory-allocation\/#Requirements-2\" >Requirements<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en7-dynamic-memory-allocation\/#Extra_task_2_W07-3_Settings\" >Extra task 2 [W07-3]: Settings<\/a><ul class='ez-toc-list-level-5' ><li class='ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en7-dynamic-memory-allocation\/#Requirements-3\" >Requirements<\/a><\/li><\/ul><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en7-dynamic-memory-allocation\/#After_this_class_you_should\" >After this class, you should<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en7-dynamic-memory-allocation\/#Additional_materials\" >Additional materials<\/a><\/li><\/ul><\/nav><\/div>\n<h3><span class=\"ez-toc-section\" id=\"Lab_materials\"><\/span>Lab materials<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<ul>\n<li>Slides: <a href=\"https:\/\/blue.pri.ee\/ttu\/files\/iax0584\/slaidid-en\/07_dynamic_memory_management.pdf\"><strong>Dynamic memory 1<\/strong><\/a><\/li>\n<\/ul>\n<h3><span class=\"ez-toc-section\" id=\"Lab_tasks\"><\/span>Lab tasks<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>For this week, you will be creating a random data generator as the base task. This task is extended by two extra tasks. Similarly built generators are used in multiple places throughout the course to generate data files.<\/p>\n<p>NB! One recommendation to generate data files has been to use LLMs for this. While good for short files, it doesn&#8217;t work well (or gets very costly) if you wish to generate millions of lines of complex data.<\/p>\n<h4><span class=\"ez-toc-section\" id=\"Task_1_W07-1_Random_data_file_generator\"><\/span>Task 1 [W07-1]: Random data file generator<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>The first task is to generate a program to generate random data files.\u00a0These are useful for testing other applications without having access to real data.<\/p>\n<p><strong>Download the starter code: <a href=\"https:\/\/blue.pri.ee\/ttu\/files\/iax0584\/aluskoodid\/7_generator_starter.zip\">https:\/\/blue.pri.ee\/ttu\/files\/iax0584\/aluskoodid\/7_generator_starter.zip<\/a><\/strong><\/p>\n<h5><span class=\"ez-toc-section\" id=\"Requirements\"><\/span>Requirements<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<ul>\n<li>Build your application on the starter code provided<\/li>\n<li>Ask the user how many entries they wish to generate. There must be no upper bound!<\/li>\n<li>All entries are stored in a struct array during generation. Struct array itself is generated using dynamic memory allocation.<\/li>\n<li>Pick a random first and last name and curriculum code from the pools of predefined values<\/li>\n<li>Generate admission points as a random number (e.g. 24.7)\n<ul>\n<li>Range must be from 10.0 to 30.0, ends inclusive.<\/li>\n<li>Precision must be\u00a0 0.1 points<\/li>\n<\/ul>\n<\/li>\n<li>Sort the generated entries based on the last name. If last names for two entries match, order those by their first name.<\/li>\n<li>Write the output to a file in the following format:<br \/>\n<span class=\"lang:default highlight:0 decode:true crayon-inline\">&lt;index&gt; &lt;last name&gt; &lt;first name&gt; &lt;curriculum code&gt; &lt;admission points&gt;<\/span><\/p>\n<ul>\n<li>Index is a unique integer. First entry will have the index as 0, every following one is incremented by one<\/li>\n<\/ul>\n<\/li>\n<li>Make sure that all resources (including memory) is freed when the program exits, use valgrind to make sure.<\/li>\n<\/ul>\n<h5><span class=\"ez-toc-section\" id=\"Workflow\"><\/span>Workflow<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<ul>\n<li>Write the necessary structure declaration for the data in the header file.<\/li>\n<li>Ask the user how many entries they want to generate<\/li>\n<li>Allocate the memory, check for allocation failures<\/li>\n<li>Generate the necessary entries\n<ul>\n<li>Every person will have all their members generated randomly<\/li>\n<li>For the struct members that are picked out of the pools, you must generate a random number to pick it out<br \/>\n<em>Hint: you can either copy the name to your struct or only keep a pointer to the name<\/em><\/li>\n<li>Generate the admission points (10.0 &lt;= points &lt;= 30.0, precision 0.1)<br \/>\n<em>Hint: Think about this mathematically &#8211; e.g. what&#8217;s the difference between 30 and 300!? rand() function will always give you an int, regardless if what you try to do to it.<\/em><\/li>\n<\/ul>\n<\/li>\n<li>Sort the array\n<ul>\n<li>Think why is it bad idea to use bubble\/selection\/insertion sort here!<\/li>\n<\/ul>\n<\/li>\n<li>Write the results to an output file<\/li>\n<li>Free the dynamically allocated memory<\/li>\n<\/ul>\n<p>Check with Valgrind for correctness! Not only in the end, but also if you encounter some weirdness, crashes or corruption!<\/p>\n<h5><span class=\"ez-toc-section\" id=\"Qsort_comparison_function\"><\/span>Qsort comparison function<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p>I&#8217;m proposing two different comparison function options. Pick the one that you understand better or write your own.<\/p>\n<p>In the first case, the type cast will be done as needed, removing the need for additional variables.<\/p>\n<pre class=\"toolbar:1 lang:c decode:true\">int ComparCandidate(const void *a, const void *b)\r\n{\r\n    \/\/ Get comparison for last names\r\n    int ret = strcmp(((candidate *)a)-&gt;lName, ((candidate *)b)-&gt;lName);\r\n    \r\n    \/\/ When last names match, return difference by first name\r\n    if (ret == 0)\r\n        return strcmp(((candidate *)a)-&gt;fName, ((candidate *)b)-&gt;fName);\r\n    \r\n    \/\/ Return difference by last name\r\n    return ret;\r\n}<\/pre>\n<p>In the second case, temporary pointers are used that take will up some memory, but improve the readability of the code.<\/p>\n<pre class=\"toolbar:1 lang:c decode:true \">int ComparCandidate(const void *a, const void *b)\r\n{\r\n    \/\/ Temporary cast pointers for readability\r\n    candidate *pA = (candidate *)a;\r\n    candidate *pB = (candidate *)b;\r\n\r\n    \/\/ Get comparison for last names\r\n    int ret = strcmp(pA-&gt;lName, pB-&gt;lName);\r\n    \r\n    \/\/ When last names match, return difference by first name\r\n    if (ret == 0)\r\n        return strcmp(pA-&gt;fName, pB-&gt;fName);\r\n    \r\n    \/\/ return difference by last name\r\n    return ret;\r\n}<\/pre>\n<h5><span class=\"ez-toc-section\" id=\"Testing\"><\/span>Testing<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p>The output of your application should be relatively simple and short.<\/p>\n<pre class=\"theme:cisco-router toolbar:2 nums:false nums-toggle:false lang:default highlight:0 decode:true\">risto@risto-lt3-tux:~\/Nextcloud\/work\/ttu\/teaching\/_generic\/prog2\/lab\/wk7_generator\/generator_solution$ valgrind .\/generator\r\n==12389== Memcheck, a memory error detector\r\n==12389== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.\r\n==12389== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info\r\n==12389== Command: .\/generator\r\n==12389==\r\nThe database contains:\r\n103 first names\r\n105 last names\r\n3 curriculum codes\r\n\r\nHow many candidates to generate?\r\n&gt; 500\r\n\r\nSuccessfully generated 500 entries\r\nSuccessfully written 500 lines to generated_candidates.txt\r\n==12389==\r\n==12389== HEAP SUMMARY:\r\n==12389==     in use at exit: 0 bytes in 0 blocks\r\n==12389==   total heap usage: 6 allocs, 6 frees, 13,016 bytes allocated\r\n==12389==\r\n==12389== All heap blocks were freed -- no leaks are possible\r\n==12389==\r\n==12389== For lists of detected and suppressed errors, rerun with: -s\r\n==12389== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)\r\n<\/pre>\n<p>Then take a look at the output file and make sure the results are correct. You will have a different result because all fields will be generated randomly.<\/p>\n<pre class=\"toolbar:2 lang:default highlight:0 decode:true \">0 Aas Heidy IACB 27.9\r\n1 Aas Juhan IACB 29.6\r\n2 Aas Reet IACB 18.2\r\n3 Aasa Anne EARB 10.1\r\n4 Aasa Julia MVEB 13.8\r\n5 Aasa Sven EARB 14.5\r\n6 Aasa Taavi MVEB 16.1\r\n7 Aasa Urve EARB 29.4\r\n8 Aasa Valdo IACB 21.2\r\n9 Allik Ivari IACB 21.3\r\n10 Allik Kerttu MVEB 29.8\r\n11 Allik Kerttu MVEB 21.4\r\n12 Allik Laivi MVEB 24.2\r\n13 Allik Peeter IACB 22.3\r\n14 Allik Rainer IACB 17.5<\/pre>\n<h4><span class=\"ez-toc-section\" id=\"Extra_task_1_W07-2_Output_file_formats\"><\/span>Extra task 1 [W07-2]: Output file formats<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>In this task, you will need to add CSV as a secondary output format for our application. User must be able to choose which output format they want.<\/p>\n<h5><span class=\"ez-toc-section\" id=\"Requirements-2\"><\/span>Requirements<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<ul>\n<li>Add ability to your program to generate data in the CSV format\n<ul>\n<li>First line of the CSV must be the header with the field names.<\/li>\n<li>This will be followed by data lines. Each member on a line is separated by a comma. NB! Do not put a space after the comma for CSV file!<\/li>\n<\/ul>\n<\/li>\n<li>Ask the user for which output file format they need (CSV or space delimited). Generate the appropriate type of file.<\/li>\n<li>For the space-delimitted file, the extension must be <span class=\"lang:default highlight:0 decode:true crayon-inline\">.txt<\/span>\u00a0 and for the CSV file, use the extension\u00a0 <span class=\"lang:default highlight:0 decode:true crayon-inline\">.csv<\/span> .<\/li>\n<li>Make sure that the CSV is correctly generated &#8211; try to open (or import) it using\u00a0 Libreoffice Calc&#8217;i\u00a0 or Microsoft Office and see if they recognize the format correctly.<\/li>\n<\/ul>\n<h4><span class=\"ez-toc-section\" id=\"Extra_task_2_W07-3_Settings\"><\/span>Extra task 2 [W07-3]: Settings<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>In this task, you will need to make the generation a bit more flexible. This require adding options to select which fields are generated and what the points range is going to be.<\/p>\n<h5><span class=\"ez-toc-section\" id=\"Requirements-3\"><\/span>Requirements<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<ul>\n<li>All settings must be kept in a structure &#8211; create a new structure<\/li>\n<li>All settings must have default values<\/li>\n<li>Program must use the defaults if the user does not wish to change the settings. What the user needs to do to alter the settings is up to you<br \/>\n<em>E.g. you can ask inside of the program if they wish to alter the settings or use command line arguments<\/em><\/li>\n<li>User must be able to alter the following settings without editing the source code\n<ul>\n<li>Which data fields are generated (it must be possible to turn each one of them on or off).<\/li>\n<li>Name of the output file (only the name part. Extension must be chosen automatically based on the output format!)<\/li>\n<li>Output format (this is from extra task 1, move the location of the setting into the struct).<\/li>\n<li>Number of items generated (from the base task, move the variable for the setting to the struct)<\/li>\n<li>Lower rand upper bounds for the admission points<\/li>\n<\/ul>\n<\/li>\n<li>NB! The number of entries generated must be asked regardless if the user wished to change the settings or not. Purpose of this is just to keep all settings neatly in one struct.<\/li>\n<li>User must be shown the settings the generation will be performed under regardless if they chose to edit it or not.<\/li>\n<\/ul>\n<p>Note: if you wish, you can make a settings file, however it is not necessary. The alterations to the default settings do not need to be stored between executions. However if you do include a settings file, make sure that the user can change those settings within the program without editing the file manually.<\/p>\n<p>Hint: You can make nice use of the ternary operator here<br \/>\n<span class=\"lang:default decode:true crayon-inline\">printf(&#8220;First name: %10s\\n&#8221;, settings.genFirstName ? &#8220;Yes&#8221;: &#8220;No&#8221;); <\/span><\/p>\n<h3><span class=\"ez-toc-section\" id=\"After_this_class_you_should\"><\/span>After this class, you should<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<ul>\n<li>Know how to use dynamic memory allocation<\/li>\n<li>Know how to check for memory leaks<\/li>\n<li>Know in which situations it is reasonable to use dynamic memory and in which situations you should not<\/li>\n<li>Know the difference between function call stack and heap<\/li>\n<li>Know the differences between malloc and calloc<\/li>\n<\/ul>\n<h3><span class=\"ez-toc-section\" id=\"Additional_materials\"><\/span>Additional materials<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<ul>\n<li>Manual memory allocation<br \/>\n<strong><a href=\"https:\/\/beej.us\/guide\/bgc\/html\/split\/manual-memory-allocation.html#manual-memory-allocation\">https:\/\/beej.us\/guide\/bgc\/html\/split\/manual-memory-allocation.html#manual-memory-allocation<\/a><\/strong><\/li>\n<li>Memory leaks in C<br \/>\n<strong><a href=\"https:\/\/www.geeksforgeeks.org\/what-is-memory-leak-how-can-we-avoid\/\">https:\/\/www.geeksforgeeks.org\/what-is-memory-leak-how-can-we-avoid\/<\/a><\/strong><\/li>\n<li>Checking for memory leaks using Valgrind<br \/>\n<strong><a href=\"https:\/\/valgrind.org\/docs\/manual\/quick-start.html\">https:\/\/valgrind.org\/docs\/manual\/quick-start.html<\/a><\/strong><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Lab materials Slides: Dynamic memory 1 Lab tasks For this week, you will be creating a random data generator as the base task. This task is extended by two extra tasks. Similarly built generators are used in multiple places throughout the course to generate data files. NB! One recommendation to generate data files has been &hellip; <a href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en7-dynamic-memory-allocation\/\" class=\"more-link\">Loe edasi <span class=\"screen-reader-text\">PR2EN7: Dynamic memory allocation<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[75,105],"tags":[],"class_list":["post-8314","post","type-post","status-publish","format-standard","hentry","category-labs","category-pr2_en"],"_links":{"self":[{"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/posts\/8314","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/comments?post=8314"}],"version-history":[{"count":12,"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/posts\/8314\/revisions"}],"predecessor-version":[{"id":11310,"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/posts\/8314\/revisions\/11310"}],"wp:attachment":[{"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/media?parent=8314"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/categories?post=8314"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/tags?post=8314"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}