提问人:Osiris85 提问时间:11/16/2023 更新时间:11/16/2023 访问量:68
C 动态数组中的内存限制超出
Memory Limit Exceed in C dynamic array
问:
我正在尝试使用内存分配创建一个 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 数组作为参数,所以我只能通过除法来找到大小。
原来我的程序不够优化。
答:
3赞
Lundin
11/16/2023
#1
首先,我强烈建议放弃指针到指针,而是将其全部分配为快速连续的 3D 数组。正确分配多维数组
因为 free 函数只传递 3d 数组作为参数,所以我只能通过除法来找到大小。
不,你不能那样做。任何地方都没有存储有关数组大小的信息,程序员的工作是跟踪这些信息。 它主要是一个编译时运算符,所以它对一些动态数组有多大没有神奇的知识。相反,你得到的是指针的大小(以字节为单位)。有关详细信息,请参阅如何查找数组的大小(从指向第一个元素数组的指针)?。sizeof
因此,您需要使用 3 个大小参数进行声明。值得注意的是,如果你使用3D数组,这不会是一个问题,那么你可以只在一行上。delete_3d_array
free(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
您没有 3d 数组,只有指针数组。
当你传递指针时,你无法获得数组的大小,因为只会给你指针的大小,而不是引用的对象
sizeof
使用数组指针
不要用作变量名称。它看起来并不“骇人听闻”
_
使用更有意义的变量名称。
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在哪里?我看不出来。我更改了一些变量名称以使其更有意义
评论
sizeof(arr)/sizeof(arr[0])
m*n*k
m*n*k*
[x+y*m+z*m*n]
[x][y][z]
[i][j][k]
_