我正在研究一个数值程序来近似双曲方程的解。
我必须在for循环的每次迭代中为两个1d数组和两个2d数组分配内存。所以我在每次迭代中都分配了内存和free
内存。
代码是
int main()
{
int mesh, n_max, m_max;
int i;
double v, delta_t, delta_x, lambda;
double *t, *x, **u, **u_exact, error[MAX_MESH];
for (mesh = 0; mesh < MAX_MESH; mesh++) {
m_max = pow(2, 5) * pow(2, mesh);
n_max = 16 * m_max;
t = vector_alloc((n_max + 1) * sizeof(double));
x = vector_alloc((m_max + 2) * sizeof(double));
u = matrix_alloc(m_max + 2, n_max);
u_exact = matrix_alloc(m_max + 2, n_max);
//functions manipulating t, x, u, u_exact
free(t);
free(x);
for (i = 0; i < m_max + 2; i++) free(u[i]);
free(u);
for (i = 0; i < m_max + 2; i++) free(u_exact[i]);
free(u_exact);
}
return (0);
}
double *vector_alloc(int n)
{
double *result; /* ponteiro para o vetor */
result = malloc(n * sizeof(double));
if (result == NULL) printf("Error: no memmory available");
return(result);
}
double **matrix_alloc(int m, int n)
{
int i;
double **result;
/* Allocates matrix raws */
result = malloc(m * sizeof(double *));
if (result == NULL) {
printf ("Error: no memmory available");
return (NULL);
}
/* Allocates matrix columns */
for (i = 0; i < m; i++) {
result[i] = malloc(n * sizeof(double));
if (result[i] == NULL) {
printf ("Error: no memmory available");
return (NULL);
}
}
return (result);
}
free
语句不起作用。如果我尝试仅free
1d阵列t
和x
,则在第二次迭代后,我会收到segmentation fault
错误。
如果只尝试free
二维数组u
和u_exact
,我会收到错误
*** glibc detected *** ./a.out: double free or corruption (!prev): 0x0900a968 ***
答案 0 :(得分:0)
我怀疑你的内存不足。内存分配似乎在循环中呈指数级增长。
对于MAX_MESH为8,如果我们采用最后一次迭代,那将是最坏的情况:
我假设双倍大小是8个字节。
m_max = 2 ^ 12
n_max = 2 ^ 16
所需内存以字节为单位:
t =(2 ^ 16 + 1)*(2 ^ 3)= 2 ^ 19 + 2 ^ 3
x =(2 ^ 12 + 1)*(2 ^ 3)= 2 ^ 15 + 2 ^ 3
u =(2 ^ 12 + 2)*(2 ^ 16)*(2 ^ 3)= 2 ^ 31 + 2 ^ 20(约)
u_exact = 2 ^ 31 + 2 ^ 20(约)
为简洁起见,我遗漏了将每个行指针存储在u和u_exact计算中所需的内存。
查看u和u_exact所需的大量内存!
现在,如果您在32位系统中运行,那么您的进程肯定没有足够的虚拟内存可供使用。我希望有一个&#34; NULL&#34; malloc在矩阵分配函数中返回的指针。您是否正在检查返回值并打印类似于您在vector_alloc中执行的操作的错误消息(如下所示)?
double **matrix_alloc(int m, int n)
{
int i;
double **p = malloc(sizeof(double **) * m);
if(!p) {printf("matrix_alloc:: Unable to allocate memory!!! \n");}
for (i = 0; i < m; i++)
{
p[i] = malloc(sizeof(double) * n);
if(!p[i]) {printf("matrix_alloc:: Unable to allocate memory!!! \n");}
}
return p;
}
如果请求的分配很大(默认值为128 KB),malloc会调用mmap。请参阅http://man7.org/linux/man-pages/man3/malloc.3.html。 mmap受RLIMIT_DATA资源限制的限制。您可以通过运行命令&#34; ulimit -v&#34;来检查系统中进程的虚拟内存限制。如果它返回&#34;无限制&#34;那就没有限制了。
我们可以通过将MAX_MESH值减小到4(如果要检入32位机器)来确认内存是否有问题。如果你在64位机器上运行相同的程序,我希望它会很好,因为可用的虚拟内存必须足以使你的MAX_MESH值为8。
答案 1 :(得分:0)
代码耗尽内存,并输出错误,但仍然继续,好像分配有效!
代码需要更改u
和u_exact
的释放。
// for (i = 0; i < m_max + 2; i++) free(u[i]);
if (u != NULL) for (i = 0; i < m_max + 2; i++) free(u[i]);
由于分配的矩阵指针和分配的部分列都丢失,因此以下内存泄漏。可以释放分配的部件或错误,如下所示。存在其他方法。
/* Allocates matrix columns */
for (i = 0; i < m; i++) {
result[i] = malloc(n * sizeof(double));
if (result[i] == NULL) {
// add 2 lines
do { free(result[i]); } while (i-- > 0);
free(result);
printf ("Error: no memmory available");
return (NULL);
}
}
对于数组大小使用size_t
而不是int
是C方式,因为int
的大小不是调整内存大小时使用的确定类型。请注意,size_t
是未签名的。
同时分配内存是另一种方法。这可能有alligmnet问题,因此接下来是2分配方法。
void matrix_free(double **ptr) {
if (ptr) {
free(*ptr);
free (ptr);
}
}
double **matrix_alloc(size_t m, size_t n) {
double **result = malloc(m * sizeof *result);
double *data = malloc(m * n * sizeof *data);
if (result == NULL || data == NULL) {
free(result);
free(data);
printf ("Error: no memmory available");
return (NULL);
}
for (size_t i=0; i<m; i++) {
result[i] = &data[i*n];
}
return result;
}
void foo(void) {
double **mat = matrix_alloc(3,4);
...
matrix_free(mat);
mat = NULL;
}