如何在 C++ 中正确管理动态分配的指针数组?

How to properly manage dynamically allocated pointer arrays in C++?

目前我正在研究只有小 RAM 容量 (128 MB) 的微处理器。我是运行多线程执行来分析性能但是问题的本质在于动态存储大量数据(浮点数和整数)space以减少数据[=的可能性19=] 向量等数据结构在执行中往往依赖。

我决定测试一些关于如何在 CLion 中解决这个问题的可能方案。我写了下面的代码:

#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;
}

我试图生成一个三重数组,以便在最后一个子集中存储相同数量的信息,同时它的大小和总量不断增加。但是,为了完成进程的动态方面而删除数组的过程总是导致 Process finished with exit code -1073740940 (0xC0000374),这是一个堆损坏错误。我对此不是很熟悉,对此的任何反馈都会有所帮助。

例程 resizeArray 在其内部循环的每次迭代中将 current_capacitycurrent_capacity*=2; 加倍。第一次调用时,这导致 arr[0][0] 被设置为指向内存 6 int,而循环继续并最终将 current_capacity 设置为 1536。对于程序的其余部分执行时,resizeArray 永远不会分配更多内存,因为它从未达到相对于 current_capacity 的阈值。

与此同时,main 例程继续向 generated[0][0] 写入越来越多的元素,将 current_count 增加到 20,因此超出了分配内存的范围。

这个错误可以通过将 current_capacity*=2; 移出循环,移到 if(percentage >= 0.5) 的“then”块内来修复。

另请注意,将多维数组实现为指针到指针或指针到指针到指针的技术在时间和 space 上效率低下。 “指针追逐”不利于处理器对指令的推测执行。对于固定大小的多维数组,这不用于生产质量代码。在这种需要可变最后一维的情况下,选择不太明确,但使用一个连续的内存分配和使用索引算法计算数组中的位置而不是指针查找可能仍然更可取。 (C 使用可变长度数组使这相当简单,尽管对它们的支持是可选的。C++ 实现可以提供可变长度数组作为扩展,但必要的算法并不难,可以使用辅助函数或 类 完成。 )