Dynamic Allocation and Contiguous Lists
Objectives
- Know how to use contiguous lists in
C. - Know how to dynamically allocate a vector and a matrix
- Know how to use the
reallocfunction
Questions
malloc
Difficulty: Rx
- In a file
alloc_statique.c, declare a function with an integer matrixMof sizeSIZE*SIZEwhereSIZEis a constant (for example, equal to 400 to start), and initialize the matrix. Compile and test. Increase the constantSIZEand observe the limits of stack allocation. Note at what size your code stops working, and how many bytes/kilobytes that corresponds to. - In the same file, now declare the matrix
Mas a global variable, and test the allocation limits in the data segment. Report the limits. - In a file
alloc_dynamique.c, declareint * v, allocate and initialize a vector ofSIZEintegers. For this, use themallocfunction which allows dynamic memory allocation; thusint * v = (int *) malloc(SIZE * sizeof(int));allocatesSIZEelements of integer size. Ifmallocfails (not enough memory), the returned value isNULL. - In the file
alloc_dynamique.c, declareint ** mat, allocate and initialize a matrix of sizeSIZE*SIZE: the matrix is a vector of vectors. To simplify these allocations, you can use a loop that allocates a vector at each iteration and assigns it to the matrix. - Test the allocation limits on the heap by printing the total allocated memory
size the first time
mallocreturnsNULL. To find the limits, change the size of the vectors (for example, allocate 1 megabyte per iteration, 10 megabytes per iteration, 100 megabytes per iteration, 1 gigabyte per iteration, …). - Properly deallocate the matrix using the
freecommand. For example for question 3, the statementfree(v)frees the memory allocated byv. Verify there are no memory leaks using thevalgrindutility1
realloc
Difficulty: Rx
Given the following source code:
realloc-example.c
#include <stdio.h>
#include <ctype.h>
int main()
{
char character = getchar();
while ( !isspace(character) )
{
putchar(character);
character = getchar();
}
putchar('\n');
return 0;
}
- What does the
isspacefunction do? You can use page 3 of the manual (man). - Modify this program to store the characters in a dynamically allocated vector
as they are read. Be careful not to exceed the bounds of the allocated vector
(add a stopping condition in the
whileloop). Also be careful to properly deallocate the vector at the end of execution. - Consult the documentation of the
reallocfunction (man realloc). - Use the
reallocfunction to resize the vector when the bounds are reached (for example, add 8 characters to it), so that input only ends when a whitespace character (' ','\n','\t', …) is read. Make sure to properly deallocate the vector at the end of execution. Verify withvalgrindthat there are no memory leaks.
String Structure
Difficulty: HardTo simplify the writing of string algorithms, and to no longer worry about
dynamic allocation, we will encapsulate character strings in a structure, and
write the basic functions for this structure. In a new file chaine.c:
chaine.c
typedef struct
{
char * data;
int alloc;
int size;
} chaine ;
The meaning of this structure is as follows:
- The
datafield holds the address of a dynamically allocated memory region containing a character string (terminated by'\0'). - The
allocfield holds the number ofcharvalues allocated fordata. - The
sizefield holds the length of the string (the'\0'is not counted) - We always have
size+1 <= alloc.
- Declare the type
chaine. - Write the function
void init_chaine(chaine *)which initializes theallocandsizefields to 0, anddatatoNULL. - Write the function
void clean_chaine(chaine *)which deallocates the dynamically allocated memory for the string. - Write the function
void print_chaine(chaine *)which prints the string data. - Write a function
void concat_chaine_char(chaine *, char)which appends a character to the end of the string, resizing thedatafield if necessary (withrealloc). - Test these functions in the same way as before: initialization, copying characters requested from the user, then printing and finally deallocation.
- Write a function
void concat_chaine_chaine(chaine *, chaine *)which appends all characters from the second string to the end of the first, resizing thedatafield if necessary (withrealloc). Test this new functionality.
Footnotes
-
See the documentation to learn how to use valgrind https://valgrind.org/docs/manual/quick-start.html#quick-start.intro ↩