Acquiring More Land 1.0.2

Malloc bugs, issues & advanced


If there is a conflict between the subject and the skeleton or moulinette, the subject is always right.
However, please report any inconsistencies to your assistant.

Submissions

Repository structure
At the end, your git repo must follow this architecture:
prog-103-p-03-2030-firstname.lastname
├── AcquiringLand
│   ├── Fundamentals
│   │   ├── bad_practice.c
│   │   ├── insert_string.c
│   │   ├── itoa.c
│   │   ├── join_strings.c
│   │   ├── leaks.c
│   │   ├── magic_arrays.c
│   │   ├── minefield.c
│   │   └── trespass.c
│   └── Proficiencies
│       ├── normalize_array.c
│       ├── split_by_sum.c
│       └── unique_words.c
├── .gitignore
└── README

Do not forget to check the following requirements before submitting your work:
  • You shall obviously replace firstname.lastname with your login.
  • The .gitignore file is mandatory.
  • Remove all personal tests from your code, except those from the Tests folder.
  • The given prototypes must be strictly respected.
  • The code MUST compile! Otherwise you will not receive a grade.

Introduction


Lore
Your island is growing. New residents are arriving, new buildings are planned, and suddenly... the space you started with is no longer enough. Like last week's practical, you can ask Tom Nook for permission to acquire more land, dynamically.
In this practical, you will learn how to expand your island using malloc, realloc, and free, and more importantly, how to manage this land responsibly!
Every new plot you acquire must eventually be maintained… or released.

Warning(s)
For this practical, the only libraries allowed are the following.
They import basic functions that you will need later in this practical.
It is your responsibility to add them.

Code example(s)
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

Hint(s)
You can enter in a terminal man stdio.h (or replace it with any other built-in command or library name) to view its manual page.
You can also do man 3 <function> to have the documentation of the function you want.

Danger(s)
As usual, all of your functions prototypes MUST be EXACTLY the same as the ones in the subject (except for the ; of course). Otherwise, your code will not be tested.

Lore
In the last practical, you decided to expand your island with Tom Nook, and we will now go into more detail on how to maintain this newly acquired land.
If you don’t maintain it correctly, your island will slowly fill up with abandoned plots, unstable bridges, and unsafe constructions… and Tom Nook will not be happy.
This is why we will now guide you through maintaining the plots you have acquired.



Fundamentals/itoa.c


This function will be used as a helper for the my_itoa function.
Write a function that computes the number of characters required to represent the given integer value, including the minus sign if the value is negative.

Prototype(s)
int get_number_length(int value);

Code example(s)
get_number_length(7);       //1
get_number_length(-97163);  //6
get_number_length(82622);   //5

Write a function that takes an integer value and convert it to a string.
You must return a pointer to a dynamically allocated, null-terminated string containing the decimal representation of the integer value.
The caller will be responsible for freeing the string.
If malloc(3) or calloc(3) fails, you must return NULL.

Hint(s)
Use the get_number_length() function you just implemented.
For the curious, this function does the reverse of atoi(3) from <stdlib.h>.

Prototype(s)
char *my_itoa(int value);

Code example(s)
my_itoa(-172);     // "-172"
my_itoa(2);        // "2"
my_itoa(-2829302); // "-2829302"



Fundamentals/minefield.c


For this exercise, you just need to open the file minefield.c given in the assets.tar.gz.
You do not need to understand the code.
Your task is to remove all of the problematic lines for the code to compile and run smoothly.
You do not need to add anything, just delete a few lines.

To do this, you must compile using the AddressSanitizer with the flag -fsanitize=address.
When enabled, the program is instrumented to detect common memory errors such as :
  • Use of uninitialized memory
  • Access of freed memory (use-after-free)
  • Buffer overflows
  • Invalid memory reads or writes
  • Double free
  • And of course, memory leaks

When an error occurs, AddressSanitizer stops the program and prints a detailed error report in stderr.

We usually combine the -fsanitize=address with the -g flag.
The -g flag tells the compiler to include debug symbols in the executable.
It allows the AddressSanitizer (and also debuggers like gdb) to:
  • map memory addresses to source code lines which is very useful
  • show file names and line numbers
  • display full names

Without -g, we would have:

Code example(s)
ERROR: AddressSanitizer: heap-buffer-overflow
    at 0x7f3c2a1b...

With -g, it transforms in:

Code example(s)
ERROR: AddressSanitizer: heap-buffer-overflow
    at minefield.c:142
    in problematic_function

Good luck finding the bugs!
Here is the expected output of the given code after all bugs are deleted:

Output
key2: value2
key1: new_value1
Retrieved key1: new_value1
key1: new_value1
Everything is ok!

Hint(s)
The errors are located in the provided function, not in the main.
You can leave the main function in the file, it will not cause any issues.
If you think you made a mistake, you can always re-download the assets.tar.gz archive from the intranet or use git restore <file> to restore the file to the last commit made on your repository.



Fundamentals/trespass.c


For this exercise, you just need to open the file trespass.c given in the assets.tar.gz.
Your task is to modify all of the problematic lines for the code to compile and run smoothly.
You do not need to add anything, just modify a few lines.

Use the same tools you've just seen in the exercise above!

Good luck finding the bugs!
Here is the expected output of the given code after all bugs are deleted:

Output
this is a string!

Hint(s)
The errors are located in the provided function, not in the main.
You can leave the main function in the file, it will not cause any issues.
If you think you made a mistake, you can always re-download the assets.tar.gz archive from the intranet or use git restore <file> to restore the file to the last commit made on your repository.



Fundamentals/leaks.c


For this exercise, you just need to open the file leaks.c given in the assets.tar.gz.
Your task is to add a few lines of code for the code to compile and run smoothly.

The goal of this file is to highlight a category of bugs that are often invisible at runtime: memory leaks.
The program may appear to work correctly, produce no errors, and even terminate normally, yet still be wrong.
While a memory leak does not always cause an immediate crash, it can slowly consume all available memory (for example if you have a malloc(3) in a loop).
This can eventually lead to unexpected behavior, or even program crashes.

Use the same tools you've just seen in the exercises above to discover and fix the memory leaks!

There is no expected output, you just need to fix the leaks.
Good luck finding the bugs!

Hint(s)
The errors are located in the provided function, not in the main.
You can leave the main function in the file, it will not cause any issues.
If you think you made a mistake, you can always re-download the assets.tar.gz archive from the intranet or use git restore <file> to restore the file to the last commit made on your repository.



Fundamentals/bad_practice.c


For this exercise, you just need to open the file bad_practice.c given in the assets.tar.gz.
Your task is to add and modify lines for your code to compile and run smoothly.

The code contains two errors :
  • One of them is visible: it will cause the program to fail immediately.
  • The other one is invisible: the program may appear to work correctly, but it is still incorrect.
You will need to use the tools seen previously as well as -fsanitize=undefined. This sanitizer will help you detect the visible error and provide a clear error message.

Good luck finding the bugs!
Here is the expected output of the given code after all bugs are deleted:

Output
the 1st value is 21
the 2nd value is 0

Hint(s)
The errors are located in the provided function, not in the main.
You can leave the main function in the file, it will not cause any issues.
If you think you made a mistake, you can always re-download the assets.tar.gz archive from the intranet or use git restore <file> to restore the file to the last commit made on your repository.



Fundamentals/insert_string.c


Write a function that takes a dynamically allocated array of strings strings_array of size array_size.
The function must insert a copy of insert_str at position index in the array.
If the index is out of range (less than 0 or greater than or equal to array_size), insert_str must be inserted at the beginning of the array.
The array must be resized accordingly and array_size must be updated.
If strings_array is NULL, you should return NULL and do nothing.

Hint(s)
For this exercise and the following ones, only the expected input and output of the function will be provided, rather than code to paste.
You are highly encouraged to make your own main() function with your tests as this will give you even more practice using malloc(3).

Prototype(s)
char **insert_string(char **strings_array, int *array_size, char *insert_str, int index);

Code example(s)
input: {"This", "is", "a", "long", "example"}; insert_str = "very"; *array_size = 5; index = 3;
output: {"This", "is", "a", "very", "long", "example"}; *array_size = 6;

input: {"too", "short", "example"}; insert_str = "out"; *array_size = 3; index = 6;
output: {"out", "too", "short", "example"}; *array_size = 4;



Fundamentals/join_strings.c


Write a function that takes an array of strings strings of size count.
The function must return a dynamically allocated, null-terminated string containing all the strings from the array separated by a space (' ').
It is also your task to free strings once you don't need it anymore.
If strings is NULL, you should return NULL and do nothing.

Prototype(s)
char *join_strings(char *strings[], int count);

Code example(s)
input:  {"Hello", "from ", "Java", "swimming pool"}; count = 4;
output: "Hello from  Java swimming pool"

input:  {"ACDC", " are ", "the", "best"}; count = 4
output: "ACDC  are  the best"



Fundamentals/magic_arrays.c


Write a function that takes an array of integers input of size n.
The function must count the number of consecutive values and return a dynamically allocated array formatted as follows:
{value1, count1, value2, count2, ... }
You should also store the size of this array in the out_size argument.
If input is NULL, you should return NULL and do nothing.

Prototype(s)
int *compress_array(const int *input, int n, int *out_size);

Code example(s)
input:  {3, 3, 3, 1, 1, 5, 5, 5, 5}; n = 9;
output: {3, 3, 1, 2, 5, 4}; *out_size = 6;

input:  {1, 2, 3, 5, 4}; n = 5;
output: {1, 1, 2, 1, 3, 1, 5, 1, 4, 1}; *out_size = 10;


Lore
What started as a few simple plots has turned into a busy place full of paths, houses, and new facilities.
Some areas need to be reorganized, others need to be merged together, and a few unused plots must be cleared to make room for better projects.
As the island expands, it’s no longer enough to simply add land.
You must make sure every area is connected, properly maintained, and used wisely.



Proficiencies/split_by_sum.c


Write a function that takes an array of integers input of size array_size.
This function must construct and return a dynamically allocated array of integers containing the indices at which the cumulative sum of the array elements is superior or equal to the given threshold.
Each time the threshold is reached, the current index must be stored in the returned array, and the cumulative sum must then be reset to 0.
The function must store the length of the created array in out_size.

Don't worry, the function is not difficult to implement. You just need to understand what it is supposed to do by looking at the example below.

Example:
input = {4, 2, 3, 5, 6}; array_size = 5; threshold = 6;
  • You read 4, 4 < threshold, nothing happens
  • You read 2, 4+2 >= threshold, add the index of the value 2 (index = 1) to your array, and reset your sum.
  • You read 3, 0+3 < threshold, nothing happens
  • You read 5, 3+5 >= threshold, add the index of the value 5 (index = 3) to your array, and reset your sum.
  • You read 6, 0+6 >= threshold, add the index of 6 (index = 4) to your array.
  • You return your array {1, 3, 4} and it's final size in out_size.

If the threshold is never met, you should return NULL.

If input or out_size are NULL, you should return NULL and do nothing.
And finally if array_size or threshold are less or equal to 0, you should also return NULL and do nothing.

Prototype(s)
int *split_by_sum(const int *input, int array_size, int threshold, int *out_size);

Code example(s)
input : {1, 2, 3, 2, 2}; array_size = 5; threshold = 3;
output : {1, 2, 4}; *out_size = 3

input : {1, 2, 3, 2, 2}; array_size = 5; threshold = 12;
output : {}; *out_size = 0



Proficiencies/unique_words.c


Write a function that takes a string input containing multiple words separated by one or more spaces.
This function must construct a dynamically allocated, null-terminated string that contains each word only once.
If a word contains any non-alphabetical character, it must be ignored.
The function must also put the number of characters (excluding the null terminator) of the returned string inside the variable pointed by out_size.
If input or out_size are NULL, you should return NULL and do nothing.

Prototype(s)
char *unique_words(const char *input, int *out_size);

Code example(s)
input: "hello world hello c world"
output: "hello world c"; *out_size = 13

input: "This is  another wei#d d  test test"
output: "This is another d test"; *out_size = 22

Hint(s)
You might want to take a look at the following functions:
  • strcmp(3) or its sister function strncmp(3), both from the string.h header
  • isdigit(3), isalpha(3), or isalnum(3) from the ctype.h header
You are allowed to use all of these functions, just make sure to include the appropriate headers.



Proficiencies/normalize_array.c


This function is a bit tricky.
strings_array is a pointer to an array of strings which explains why it's type is char ***.
Write a function that takes such an array of size array_size and normalizes each string by removing all leading and trailing spaces.

Code example(s)
"  an  example    " -> "an  example"

If the string contains at least one occurrence of the character unwanted_char, the string must be completely removed from the array.
The array must be resized and array_size must be updated.
The same rule applies if a string is composed only of spaces: it must be removed from the array.
If the final array is empty, you should free it and the value of array_size should be set to 0.
The function will not be tested with a NULL array.

Prototype(s)
void normalize_array(char ***strings_array, int *array_size, char unwanted_char);

Code example(s)
input : *strings_array = {" an  example  ", " we_said_no_0", "normal", "  _  "}; *array_size = 4; unwanted_char = '_';
output : *strings_array = {"an  example", "normal"}; *array_size = 2;

input : *strings_array = {" make ", "yourrrrrr ", " ", " o w n", " TESTS "}; *array_size = 5; unwanted_char = 'e';
output : *strings_array = {"yourrrrrr", "o w n", "TESTS"}; *array_size = 3;


[ 1.0.2 ] 2026-03-13 18:35:00
Proficiencies
  • split_by_sum.c > split_by_sum : And finally if n or threshold are less or equal to 0... -> And finally if array_size or threshold are less or equal to 0...

[ 1.0.1 ] 2026-02-13 18:32:00
Proficiencies
  • split_by_sum.c > split_by_sum : If the threshold is never met, you should return an empty array -> If the threshold is never met, you should return NULL.


This page and all subpages are for internal use at EPITA only.
The use of this document must abide by the following rules:
Copyright © 2026-2027 - EPITA