En aquest tema, explorarem les funcions de gestió de memòria en C, que són essencials per a la manipulació dinàmica de la memòria durant l'execució d'un programa. Aquestes funcions permeten als programadors al·locar, real·locar i alliberar memòria de manera eficient.

Objectius d'Aprenentatge

Al final d'aquest tema, hauràs de ser capaç de:

  • Comprendre la importància de la gestió dinàmica de memòria.
  • Utilitzar les funcions malloc, calloc, realloc i free.
  • Identificar i evitar fuites de memòria.

  1. Introducció a la Gestió Dinàmica de Memòria

La gestió dinàmica de memòria permet als programes al·locar memòria durant l'execució, en lloc de fer-ho només en temps de compilació. Això és especialment útil quan la quantitat de memòria necessària no es coneix prèviament.

Avantatges de la Gestió Dinàmica de Memòria

  • Flexibilitat: Permet al·locar memòria segons les necessitats del programa en temps d'execució.
  • Eficiència: Pot ajudar a utilitzar la memòria de manera més eficient, alliberant memòria quan ja no és necessària.
  • Escalabilitat: Facilita la creació d'estructures de dades dinàmiques com llistes enllaçades, arbres, etc.

  1. Funcions de Gestió de Memòria

2.1 malloc

La funció malloc (memory allocation) s'utilitza per al·locar un bloc de memòria de mida especificada. Retorna un punter al primer byte del bloc al·locat.

Sintaxi:

void* malloc(size_t size);

Exemple:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *ptr;
    ptr = (int*) malloc(10 * sizeof(int)); // Al·loca memòria per a 10 enters

    if (ptr == NULL) {
        printf("Error d'assignació de memòria\n");
        return 1;
    }

    // Utilitza la memòria al·locada
    for (int i = 0; i < 10; i++) {
        ptr[i] = i + 1;
    }

    // Imprimeix els valors
    for (int i = 0; i < 10; i++) {
        printf("%d ", ptr[i]);
    }

    // Allibera la memòria
    free(ptr);

    return 0;
}

2.2 calloc

La funció calloc (contiguous allocation) s'utilitza per al·locar memòria per a un nombre específic d'elements de mida especificada i inicialitza tots els bytes a zero.

Sintaxi:

void* calloc(size_t num, size_t size);

Exemple:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *ptr;
    ptr = (int*) calloc(10, sizeof(int)); // Al·loca memòria per a 10 enters i inicialitza a zero

    if (ptr == NULL) {
        printf("Error d'assignació de memòria\n");
        return 1;
    }

    // Imprimeix els valors inicialitzats
    for (int i = 0; i < 10; i++) {
        printf("%d ", ptr[i]);
    }

    // Allibera la memòria
    free(ptr);

    return 0;
}

2.3 realloc

La funció realloc (reallocation) s'utilitza per canviar la mida d'un bloc de memòria prèviament al·locat.

Sintaxi:

void* realloc(void* ptr, size_t size);

Exemple:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *ptr;
    ptr = (int*) malloc(5 * sizeof(int)); // Al·loca memòria per a 5 enters

    if (ptr == NULL) {
        printf("Error d'assignació de memòria\n");
        return 1;
    }

    // Reassigna la memòria per a 10 enters
    ptr = (int*) realloc(ptr, 10 * sizeof(int));

    if (ptr == NULL) {
        printf("Error de reassignació de memòria\n");
        return 1;
    }

    // Utilitza la memòria reassignada
    for (int i = 0; i < 10; i++) {
        ptr[i] = i + 1;
    }

    // Imprimeix els valors
    for (int i = 0; i < 10; i++) {
        printf("%d ", ptr[i]);
    }

    // Allibera la memòria
    free(ptr);

    return 0;
}

2.4 free

La funció free s'utilitza per alliberar un bloc de memòria prèviament al·locat.

Sintaxi:

void free(void* ptr);

Exemple:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *ptr;
    ptr = (int*) malloc(10 * sizeof(int)); // Al·loca memòria per a 10 enters

    if (ptr == NULL) {
        printf("Error d'assignació de memòria\n");
        return 1;
    }

    // Utilitza la memòria al·locada
    for (int i = 0; i < 10; i++) {
        ptr[i] = i + 1;
    }

    // Allibera la memòria
    free(ptr);

    return 0;
}

  1. Exercicis Pràctics

Exercici 1

Escriu un programa que al·loqui memòria per a un array de 20 enters, inicialitzi els valors a 0 utilitzant calloc, i imprimeixi els valors.

Solució:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *arr;
    arr = (int*) calloc(20, sizeof(int));

    if (arr == NULL) {
        printf("Error d'assignació de memòria\n");
        return 1;
    }

    for (int i = 0; i < 20; i++) {
        printf("%d ", arr[i]);
    }

    free(arr);

    return 0;
}

Exercici 2

Escriu un programa que al·loqui memòria per a un array de 5 enters, després reassigni la memòria per a 10 enters, inicialitzi els nous elements a 0, i imprimeixi tots els valors.

Solució:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *arr;
    arr = (int*) malloc(5 * sizeof(int));

    if (arr == NULL) {
        printf("Error d'assignació de memòria\n");
        return 1;
    }

    arr = (int*) realloc(arr, 10 * sizeof(int));

    if (arr == NULL) {
        printf("Error de reassignació de memòria\n");
        return 1;
    }

    for (int i = 5; i < 10; i++) {
        arr[i] = 0;
    }

    for (int i = 0; i < 10; i++) {
        printf("%d ", arr[i]);
    }

    free(arr);

    return 0;
}

  1. Errors Comuns i Consells

Errors Comuns

  • No comprovar si malloc, calloc o realloc retornen NULL: Sempre comprova si la funció ha retornat NULL per evitar accessos a memòria no vàlida.
  • No alliberar memòria amb free: No alliberar memòria pot causar fuites de memòria, que poden esgotar els recursos del sistema.
  • Utilitzar memòria després d'alliberar-la: Accedir a memòria després d'haver-la alliberat pot causar comportaments indefinits.

Consells

  • Inicialitza sempre els punters: Assigna NULL als punters després d'alliberar-los per evitar accessos accidentals.
  • Utilitza calloc per inicialitzar memòria a zero: Això pot evitar errors en la inicialització de dades.

Conclusió

En aquest tema, hem après sobre les funcions de gestió de memòria en C, incloent malloc, calloc, realloc i free. Hem vist com utilitzar aquestes funcions per al·locar, real·locar i alliberar memòria dinàmica, i hem practicat amb alguns exemples i exercicis. La gestió adequada de la memòria és crucial per escriure programes eficients i lliures d'errors.

Curs de Programació en C

Mòdul 1: Introducció al C

Mòdul 2: Tipus de Dades i Variables

Mòdul 3: Flux de Control

Mòdul 4: Funcions

Mòdul 5: Arrays i Strings

Mòdul 6: Punteres

Mòdul 7: Estructures i Unions

Mòdul 8: Assignació Dinàmica de Memòria

Mòdul 9: Gestió d'Arxius

Mòdul 10: Temes Avançats

Mòdul 11: Millors Pràctiques i Optimització

Mòdul 12: Projecte i Avaluació Final

© Copyright 2024. Tots els drets reservats