我很难解决这个问题:
typedef struct {
.....
} info;
info array[1000][10][10]; //now i have this 3d matrix
对于内存优化,我想动态分配第一维:我想有一个矩阵的动态数组[10][10]。所以我声明了一个这样的指针:
info *array[10][10];
但是如何做一个malloc确实将例如N矩阵[10][10]添加到数组中呢?
我试过了:
info *array[10][10]=malloc(N*sizeof(array));
正如 WhozCraig 在 coments 和 kiranBiradar 在他的回答中所描述的那样,您试图分配:
info *array[10][10]=malloc(N*sizeof(array));
是尝试为一个或多个数组或指针数组分配。您正在为N
10x10
指针数组分配。
您打算为N
10x10
info
分配存储。为此,您需要将array
声明为指向数组info [10][10]
的指针。以这种方式声明后,您可以在单个分配中自由地为数组info
分配N 10x10
(好处是只需要一个free
(而不是为info ***
分配并要求单独分配指针、行指针,最后是每行元素(。但是要声明指向数组info [10][10]
的指针,必须将数组声明为:
info (*array)[10][10];
(注意:根据您在整个代码中使用array
的方式以及将所有元素初始化为某个默认值是否有益,您可以使用calloc
而不是malloc
。calloc
将分配并清零所有字节(将新内存归零所需的额外时间通常可以忽略不计((。
我怎样才能做数组的重新分配(以防我需要更多空间(?
由于您已将array
声明为指向数组info[10][10]
的指针,并且一次性分配了存储,因此您只需realloc
为存储创建更大的内存块。有许多分配方案可以有效地处理重新分配,您可以自由地处理它。
经验法则是通常声明存储一些合理预期的指针数量和10x10
数组info
。您保留一个计数器,用于表示当前分配的指针和数组的数量(例如nptrs
(。您保留当前已填写的数字的第二个计数器(例如ndx
- 索引的缩写(。当索引达到分配的指针和数组数时,realloc
存储量在1.5 - 2
倍之间,更新计数器以增加nptrs
,并继续运行,直到再次ndx == nptrs
,然后重复。
一个简短的例子可能会有所帮助。由于info
的成员是未定义的,因此让我们仅使用指向数组int [10][10]
的简单指针作为示例。该过程对于任何集合都是相同的,唯一的区别是sizeof *array
将更改为每个 10x10 数组分配的字节数。(如果您有其他需要动态分配的info
成员 - 这将是一个额外的要求(
重新分配时,始终将返回realloc
分配给临时指针。如果realloc
失败,它将返回NULL
,如果您将其分配给原始指针 - 您刚刚创建了内存泄漏并丢失了对原始内存块的引用。通过使用临时指针,如果realloc
失败,原始数据及其指针将保持有效。
一个示例,它只是用一个常数填充每个 10x10 数组(例如1, 2, 3, ...
(,并调用realloc
两次以将 10x10 块的分配从8
增加到16
,最后32
将是:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NMTRX 8 /* if you need constants, then #define one (or more) */
#define MSIZE 10 /* don't use "magic numbers" in your code, unless */
#define NTEST 24 /* mandatory (like scanf field-width modifiers) */
/** set single MSIZExMSIZE array to n */
void set_m_to_n (int m[MSIZE][MSIZE], int n)
{
for (int i = 0; i < MSIZE; i++)
for (int j = 0; j < MSIZE; j++)
m[i][j] = n;
}
/** print single MSIZExMSIZE array */
void print_m (int m[MSIZE][MSIZE])
{
for (int i = 0; i < MSIZE; i++) {
for (int j = 0; j < MSIZE; j++)
printf (" %2d", m[i][j]);
putchar ('n');
}
}
/** realloc to twice 'sz * *nelement' bytes returning
* pointer to reallocated block on success, NULL otherwise.
*/
void *realloc_2x (void *ptr, size_t sz, size_t *nelem)
{
char *memptr = realloc (ptr, 2 * *nelem * sz);
if (memptr == NULL) {
perror ("realloc-m");
return NULL;
} /* optionally zero all new memory */
memset (memptr + *nelem * sz, 0, *nelem * sz);
*nelem *= 2; /* update nelem (nptrs) to reflect new allocation */
return memptr; /* return pointer to new block for assignment */
}
int main (void) {
size_t ndx = 0, /* index */
nptrs = NMTRX; /* initial pointers to allocate */
int (*m)[MSIZE][MSIZE]; /* pointer to MSIZExMSIZE array */
m = calloc (nptrs, sizeof *m); /* allocate & initialize zero */
if (m == NULL) { /* validate allocation */
perror ("calloc-m");
exit (EXIT_FAILURE);
}
for (ndx = 0; ndx < NTEST; ndx++) { /* loop filling NTEST arrays */
if (ndx == nptrs) { /* check if index reached allocation */
void *tmp = realloc_2x (m, sizeof *m, &nptrs); /* realloc_2x */
if (tmp == NULL)/* validate reallocation */
break; /* don't exit on failure, original data good */
m = tmp; /* assign reallocated block to m */
}
set_m_to_n (m[ndx], ndx + 1); /* set array values to ndx+1 */
}
for (size_t i = 0; i < ndx; i++) { /* output all MSIZExMSIZE arrays */
printf ("nm[%2zu]:n", i);
print_m (m[i]);
}
free (m); /* free allocated memory */
return 0;
}
示例使用/输出
输出只是指针和每个 10x10 的数字块:
$ ./bin/arr3d_dyn_ptr2d
m[ 0]:
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
m[ 1]:
2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
...
m[23]:
24 24 24 24 24 24 24 24 24 24
24 24 24 24 24 24 24 24 24 24
24 24 24 24 24 24 24 24 24 24
24 24 24 24 24 24 24 24 24 24
24 24 24 24 24 24 24 24 24 24
24 24 24 24 24 24 24 24 24 24
24 24 24 24 24 24 24 24 24 24
24 24 24 24 24 24 24 24 24 24
24 24 24 24 24 24 24 24 24 24
24 24 24 24 24 24 24 24 24 24
在您编写的任何动态分配内存的代码中,对于分配的任何内存块,您有 2个责任:(1(始终保留指向内存块起始地址的指针,以便 (2( 当不再需要内存块时可以释放它。
必须使用内存错误检查程序来确保不会尝试访问内存或超出/超出分配块的范围写入,不会尝试读取或基于未初始化值的条件跳转,最后确认释放了已分配的所有内存。
对于Linux来说,valgrind
是正常的选择。每个平台都有类似的内存检查器。它们都易于使用,只需通过它运行您的程序即可。
内存使用/错误检查
$ valgrind ./bin/arr3d_dyn_ptr2d
==25240== Memcheck, a memory error detector
==25240== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==25240== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==25240== Command: ./bin/arr3d_dyn_ptr2d
==25240==
m[ 0]:
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
m[ 1]:
2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
...
m[23]:
24 24 24 24 24 24 24 24 24 24
24 24 24 24 24 24 24 24 24 24
24 24 24 24 24 24 24 24 24 24
24 24 24 24 24 24 24 24 24 24
24 24 24 24 24 24 24 24 24 24
24 24 24 24 24 24 24 24 24 24
24 24 24 24 24 24 24 24 24 24
24 24 24 24 24 24 24 24 24 24
24 24 24 24 24 24 24 24 24 24
24 24 24 24 24 24 24 24 24 24
==25240==
==25240== HEAP SUMMARY:
==25240== in use at exit: 0 bytes in 0 blocks
==25240== total heap usage: 3 allocs, 3 frees, 22,400 bytes allocated
==25240==
==25240== All heap blocks were freed -- no leaks are possible
==25240==
==25240== For counts of detected and suppressed errors, rerun with: -v
==25240== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
始终确认已释放已分配的所有内存,并且没有内存错误。
仔细查看,如果您有其他问题,请告诉我。
您可以使用以下解决方案:
info (*array)[10][10]=malloc(N*sizeof(*array)); //declares pointer to 2d array