C 动态数组中的内存限制超出

Memory Limit Exceed in C dynamic array

提问人:Osiris85 提问时间:11/16/2023 更新时间:11/16/2023 访问量:68

问:

我正在尝试使用内存分配创建一个 3D 数组,并释放它。但是,我的程序似乎超出了内存限制。我该如何优化它?我错过了什么?

函数.h

unsigned*** new_3d_array(unsigned n,unsigned m,unsigned k);
void delete_3d_array(unsigned ***arr);

unsigned*** new_3d_array(unsigned n,unsigned m,unsigned k){
    unsigned*** array = (unsigned***)malloc(n * sizeof(unsigned**));
    for (int i = 0; i < n; i++) {
            array[i] = (unsigned**)malloc(m * sizeof(unsigned*));
            for (int j = 0; j < m; j++) {
                    array[i][j] = (unsigned*)malloc(k * sizeof(unsigned));
            }
    }

    return array;
}

void delete_3d_array(unsigned ***arr){
    unsigned long long int n = sizeof(arr)/sizeof(arr[0]); //Get individual general size
    unsigned long long int m = sizeof(arr[0])/sizeof(arr[0][0]);
    
    for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                 free(arr[i][j]);
            }
            free(arr[i]);
    }
    free(arr);
}

main.c

#include<stdio.h>
#include"function.h"

//Sample Input
//60 100 100 100 7122

unsigned random_seed=7122;
unsigned Random(){
    return random_seed=random_seed*0xdefaced+1;
}
int main(){
    int n,m,k,_;
    scanf("%d%d%d%d%u",&_,&n,&m,&k,&random_seed);
    while(_--){
        unsigned ***arr=new_3d_array(n,m,k);
        int i,j,l;
        for(i=0;i<n;++i){
            for(j=0;j<m;++j){
                for(l=0;l<k;++l){
                    arr[i][j][l]=Random();
                }
            }
        }
        for(i=0;i<5;++i){
            unsigned a,b,c;
            a=Random()%n;
            b=Random()%m;
            c=Random()%k;
            if(i)putchar(' ');
            printf("%u",arr[a][b][c]);
        }
        puts("");
        delete_3d_array(arr);
    }
    return 0;
}


我尝试使用 for 循环来定义它。因为 free 函数只传递 3d 数组作为参数,所以我只能通过除法来找到大小。

原来我的程序不够优化。

C 多维阵列 动态规划

评论

3赞 Lundin 11/16/2023
这里的错误: .stackoverflow.com/questions/492384/......它在 free() 期间会崩溃吗?sizeof(arr)/sizeof(arr[0])
2赞 tevemadar 11/16/2023
在现实世界中,对于一个“完整的”“砖块”,人们通常会分配一个单一大小的数组,并将其索引为(其中 0<=x<m, 0<=y<n, 0<=z<k)。m*n*km*n*k*[x+y*m+z*m*n]
0赞 Osiris85 11/16/2023
@Lundin程序编译得很完美,但 MLE.我也对此表示怀疑,有没有办法在不添加参数的情况下将 n、m、k 解析为删除函数?
0赞 Lundin 11/16/2023
@tevemadar我更喜欢将其分配为数组并将其索引为,但也许这太可读了......[x][y][z][i][j][k]
0赞 Lundin 11/16/2023
此外,除非您故意混淆,否则不要像......_

答:

3赞 Lundin 11/16/2023 #1

首先,我强烈建议放弃指针到指针,而是将其全部分配为快速连续的 3D 数组。正确分配多维数组

因为 free 函数只传递 3d 数组作为参数,所以我只能通过除法来找到大小。

不,你不能那样做。任何地方都没有存储有关数组大小的信息,程序员的工作是跟踪这些信息。 它主要是一个编译时运算符,所以它对一些动态数组有多大没有神奇的知识。相反,你得到的是指针的大小(以字节为单位)。有关详细信息,请参阅如何查找数组的大小(从指向第一个元素数组的指针)?sizeof

因此,您需要使用 3 个大小参数进行声明。值得注意的是,如果你使用3D数组,这不会是一个问题,那么你可以只在一行上。delete_3d_arrayfree(array)

快速修复(未测试):

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

unsigned random_seed=7122;
unsigned Random(){
    return random_seed=random_seed*0xdefaced+1;
}
int main(){
    int x,y,z,_;
    scanf("%d%d%d%d%u",&_,&x,&y,&z,&random_seed);
    if(x==0 || y==0 || z==0)
        return 1;

    while(_--){
        unsigned (*arr)[y][z] = malloc( sizeof(unsigned[x][y][z]) );
        if(arr == NULL)
            return 1;

        for(int i=0;i<x;++i){
            for(int j=0;j<y;++j){
                for(int k=0;k<z;++k){
                    arr[i][j][k]=Random();
                }
            }
        }
        for(int i=0;i<5;++i){
            unsigned a,b,c;
            a=Random()%x;
            b=Random()%y;
            c=Random()%z;
            if(i)putchar(' ');
            printf("%u",arr[a][b][c]);
        }
        puts("");
        free(arr);
    }
    return 0;
}

评论

0赞 Osiris85 11/16/2023
哇,谢谢你为我提供了一个很棒的参考。我将与我的同事分享这些信息。
1赞 gulpr 11/16/2023 #2
  1. 您没有 3d 数组,只有指针数组。

  2. 当你传递指针时,你无法获得数组的大小,因为只会给你指针的大小,而不是引用的对象sizeof

  3. 使用数组指针

  4. 不要用作变量名称。它看起来并不“骇人听闻”_

  5. 使用更有意义的变量名称。

void *new_3d_array(size_t arrs,  size_t rows,size_t cols, unsigned long long (**array)[rows][cols])
{
    *array = malloc(arrs * sizeof(**array));
    return *array;
}

void delete_3d_array(void *arr)
{
    free(arr);
}

unsigned random_seed=7122;
unsigned Random(){
    return random_seed=random_seed*0xdefaced+1;
}
int main(){
    size_t arrs,rows,cols,flag;
    scanf("%zu%zu%zu%zu%u",&flag,&arrs,&rows,&cols,&random_seed);
    while(flag--){
        unsigned long long (*arr)[rows][cols];
        if(!new_3d_array(arrs,rows,cols,&arr)) {/* handle error */}
        
        size_t i,j,l;
        for(i=0;i<arrs;++i){
            for(j=0;j<rows;++j){
                for(l=0;l<cols;++l){
                    arr[i][j][l]=Random();
                }
            }
        }
        for(i=0;i<5;++i){
            unsigned a,b,c;
            a=Random()%arrs;
            b=Random()%rows;
            c=Random()%cols;
            if(i)putchar(' ');
            printf("%llu",arr[a][b][c]);
        }
        puts("");
        delete_3d_array(arr);
    }
    return 0;
}

https://godbolt.org/z/ozh7evh8h

评论

0赞 stark 11/16/2023
您重新定义i
0赞 gulpr 11/16/2023
@stark在哪里?我看不出来。我更改了一些变量名称以使其更有意义