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



目前我使用的微处理器的RAM容量很小(128 MB(。我正在运行多个执行线程来分析性能,但问题的本质在于在动态空间中存储大量数据(浮点和整数(,以减少矢量等数据结构在执行中往往依赖的数据复制/分配的可能性。

我决定在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 1n");
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 2n");
for (int i = 0;  i < initial_capacity; ++i) {
free(arr[i]);
}
printf("Releasing allocated arrays 3n");
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;
}

我试图生成一个三重数组,以便在最后一个子集中存储相同数量的信息,同时它的大小和总量不断增加。但是,为了完成进程的动态方面而删除数组的过程总是导致进程结束,退出代码为-103740940(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"块中来修复。

还要注意,将多维数组实现为指向指针的指针或指向指向指针的指向指针的技术在时间和空间上是低效的。"指针追逐"不利于处理器推测性地执行指令。对于固定大小的多维数组,这在生产质量代码中不使用。在这种需要变量最后一个维度的情况下,选择有点不清楚,但最好使用一个连续的内存分配,并使用索引算法来计算数组中的位置,而不是指针查找。(C通过可变长度数组使这一点变得相当简单,尽管对它们的支持是可选的。C++实现可以提供可变长度数组作为扩展,但必要的算术并不困难,可以使用辅助函数或类来完成。(

最新更新