Comment gérer correctement les tableaux de pointeurs alloués dynamiquement en C ++?


AICS2000

Actuellement, je travaille sur un microprocesseur qui n'a qu'une petite capacité de RAM (128 Mo). J'exécute plusieurs threads d'exécution pour analyser les performances, mais l'essence du problème réside dans le stockage de grandes quantités de données (flottants et entiers) dans un espace dynamique afin de réduire la possibilité de copie / allocation de données que les structures de données telles que les vecteurs tendent compter sur l'exécution.

J'ai décidé de tester quelques schémas possibles sur la manière de résoudre ce problème dans CLion. J'ai écrit le code suivant:

#include <cstdlib>
#include <cstdio>


int initial_capacity = 3;
int current_capacity = 3;
int current_count  = 0;

int*** initializeArray(){
    // initialize triple array space in memory
    int*** arr;
    /*
       3 items -> 3 data sets -> each data set starts with 3 spaces
       a "int arr[3][3][3]" but dynamically allocated
    */
    arr = (int***) calloc(current_capacity, sizeof(int**));
    for(int i = 0; i < current_capacity; i++){
        arr[i] = (int**) calloc(current_capacity, sizeof(int*));
        for(int j =0; j < current_capacity; j++){
            arr[i][j] = (int*) calloc(current_capacity,sizeof(int));
        }
    }
    return arr;
}


void resizeArray(int *** arr){
    auto max = (double) current_capacity;
    double percentage = current_count/max;
    if(percentage >= 0.5){
        for (int i = 0; i < initial_capacity; ++i) {
            for (int j = 0; j < initial_capacity; ++j) {
                current_capacity*=2;
                arr[i][j] = (int*) realloc(arr[i][j],(current_capacity)*sizeof(int));
            }
        }
    }
}

void deleteArrays(int *** arr){
    for (int i = 0; i < initial_capacity; ++i) {
        for (int j = 0; j < initial_capacity; ++j) {
            for (int k = 0; k < current_count; ++k) {
                arr[i][j][k] = NULL;
            }

        }
    }
    printf("Releasing allocated arrays 1\n");

    for (int i = 0; i < initial_capacity; ++i) {
        for (int j = 0; j < initial_capacity; ++j) {
            arr[i][j] = (int*) realloc(arr[i][j],sizeof(int));
            free(arr[i][j]);
        }
    }
    printf("Releasing allocated arrays 2\n");

    for (int i = 0;  i < initial_capacity; ++i) {
        free(arr[i]);
    }
    printf("Releasing allocated arrays 3\n");

    free(arr);
}


void printArrays(int *** arr){
    for (int i = 0; i < 3; ++i) {
        printf("Array[%d]\n", i);
        for (int j = 0; j < 3; ++j) {
            printf("Array[%d][%d]\nElements: ", i, j);
            for (int k = 0; k < current_count; ++k) {
                printf(" %d", arr[i][j][k]);
            }
            printf("\n");
        }
    }
    printf("\n");
}

int main() {
    int *** generated= initializeArray();
    int count  = 0;
    while (count < 21){
        if(count % 3 == 0) printArrays(generated);
        //verify
        resizeArray(generated);
        generated[0][0][current_count] = rand();
        generated[0][1][current_count] = rand();
        generated[0][2][current_count] = rand();
        generated[1][0][current_count] = rand();
        generated[1][1][current_count] = rand();
        generated[1][2][current_count] = rand();
        generated[2][0][current_count] = rand();
        generated[2][1][current_count] = rand();
        generated[2][2][current_count] = rand();

        current_count++;
        count++;
    }
    /* some operation with data collected */
    deleteArrays(generated);
    printf("Finished deleting dynamic arrays");
    return 0;
}

J'ai essayé de générer un triple tableau afin de continuer à stocker la même quantité d'informations dans le dernier sous-ensemble tout en augmentant en taille et en quantité totale. Cependant, la procédure de suppression du tableau afin de compléter l'aspect dynamique du processus entraîne toujours un processus terminé avec le code de sortie -1073740940 (0xC0000374) qui est une erreur de corruption de tas. Je ne suis pas très familier avec cela et tout commentaire à ce sujet serait utile.

Eric Postpischil

La routine resizeArraydouble current_capacityavec current_capacity*=2;dans chaque itération de la boucle interne. La première fois qu'il est appelé, cela se traduit par arr[0][0]un pointage vers la mémoire pendant 6 int, tandis que les boucles continuent et finalement laissent current_capacityà 1536. Pour le reste de l'exécution du programme, resizeArrayn'alloue jamais plus de mémoire, du fait que son seuil relatif à current_capacityn'est jamais atteint.

Pendant ce temps, la mainroutine continue d'écrire de plus en plus d'éléments generated[0][0], augmentant current_countjusqu'à 20 et donc écrivant au-delà des limites de la mémoire allouée.

Ce bogue peut être corrigé en current_capacity*=2;sortant des boucles, juste à l'intérieur du bloc «alors» de if(percentage >= 0.5).

Notez également que la technique d'implémentation de tableaux multidimensionnels en tant que pointeurs vers pointeurs ou pointeurs vers pointeurs vers pointeurs est inefficace dans le temps et dans l'espace. La «poursuite du pointeur» est mauvaise pour l'exécution spéculative des instructions par le processeur. Pour les tableaux multidimensionnels de taille fixe, cela n'est pas utilisé dans le code de qualité de production. Dans ce cas où une variable de dernière dimension est souhaitée, le choix est un peu moins clair, mais il peut être préférable d'utiliser une allocation de mémoire contiguë et d'utiliser l'arithmétique d'index pour calculer les emplacements dans le tableau plutôt que les recherches de pointeur. (C rend cela assez simple avec des tableaux de longueur variable, bien que leur prise en charge soit facultative. Les implémentations C ++ peuvent fournir des tableaux de longueur variable comme extension, mais l'arithmétique nécessaire n'est pas difficile et peut être effectuée avec des fonctions d'assistance ou des classes.)

Articles connexes


Comment utiliser correctement les pointeurs en C

codes zef J'essaie d'ajouter des paires (clé, valeur) à un hashmap mais je ne peux pas accéder aux valeurs après insertion. Cette table de hachage est censée gérer les collisions car j'itére le long de chaque index de hachage chaque fois qu'une collision se pr

Libérer un tableau de pointeurs alloués dynamiquement

Kabom J'étudie pour un examen et j'ai une question sur un exemple de question qui m'a été fournie: Implémentez la fonction free_array avec prototype void free_array(void *a[], int length). Le but de la fonction est de libérer la mémoire allouée dynamiquement a

Tableaux 2-D d'entrée et de sortie alloués dynamiquement en C ++

Jack Black Mon objectif est d'allouer dynamiquement un tableau bidimensionnel de sorte qu'il invite l'utilisateur à saisir la taille de la ligne et de la colonne du tableau matriciel qu'il souhaite créer. Après avoir alloué dynamiquement la taille des lignes e

Conversion implicite en const de tableaux alloués dynamiquement

Francesco Dans le code suivant, une classe possède un tableau alloué dynamiquement. Il expose un accès en lecture seule à ce tableau via une méthode publique qui effectue une conversion implicite en const. #include <array> template <class T, std::size_t N> cl