如何正确释放复合操作中使用的c矩阵

时间:2014-06-18 02:22:15

标签: c memory-management

在任务中,我使用各种基本矩阵方法,例如

-multiply -transpose -倒置 -triangularize

每个方法都使用matrx_memory_alloc(float **m,int row, int col)为结果矩阵分配内存

现在我有一种方法,在伪代码中执行类似这样的操作

float **final_function(float matrix, int row, int col){
   float **result= invert(multiply(matrix,transpose(matrix, int row, int col),  int row, int col)
   return result
}

我还有一个方法matrx_memory_dealloc(float **m, int row, int col),它以分配的类似方式释放内存。

现在:

如何正确释放与final_function相关的每个方法中完成的每个内存分配?换句话说:我什么时候应该调用释放方法?

如果我在final_function之后调用释放方法,据我所知,应该只释放最终函数中使用的最后一个分配,而不是之前所有相关方法的分配。我错了吗?

2 个答案:

答案 0 :(得分:2)

假设你真的想要一些可编译的代码:

float **invert(float **matrix, int row, int col);
float **transpose(float **matrix, int row, int col);
float **multiply(float **matrix1, int row1, int col1, float **matrix2, int row2, col2);

float **final_function(float **matrix, int row, int col)
{
   float **result = invert(multiply(matrix, row, col, transpose(matrix, row, col), row, col), row, col);
   return result;
}

(主要区别是在调用3个函数的行中丢失int),然后你就像写入一样隐藏到任何东西。无法释放由函数分配的内存。您必须更明确地编写代码:

float **invert(float **matrix, int row, int col);
float **transpose(float **matrix, int row, int col);
float **multiply(float **matrix1, int row1, int col1, float **matrix2, int row2, col2);

float **final_function(float **matrix, int row, int col)
{
    float **t1 = transpose(matrix, row, col);
    float **t2 = multiply(matrix, row, col, t1, col, row);  // Dubious dimensions
    float **result = invert(t2, row, col);
    mtrix_memory_dealloc(t1, col, row);
    mtrix_memory_dealloc(t2, row, col);  // Dubious dimensions
    return result;
}

这段代码更像是一个原则'比完全工作的代码。您需要知道输出矩阵的大小。我推断,当输入为(row x col)时,转置的输出矩阵有(col x row);我没有坐下来考虑multiply()输出的大小(但它是(行x行)或(col x col),除非我完全偏离基础)。在这种情况下,对invert()的调用是错误的 - 除非row == col;它应该是invert(t2, row, row)invert(t2, col, col)。同样可以修复对mtrix_memory_dealloc(t2, …)的调用。

显然,您可以在致电t1之前免费invert()


但是我的代码仍然崩溃了?

您没有向我们展示main()transposeMatrix()功能,因此我们无法说明您的代码崩溃的原因。问题不在于您的内存分配或释放功能。在这里,我们通过实施transposeMatrix()matrix_print()函数将其嵌入(未更改)到程序中:

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

extern void matrix_print(const char *tag, int m, int n, float **matrix);

extern float **transposeMatrix(int m, int n, float **matrix);
extern float **matrx_memory_alloc(int m, int n);
extern void matrx_memory_dealloc(int m, float **array);

float **matrx_memory_alloc(int m, int n)
{
    int i;
    float **arr = malloc(m * sizeof(*arr));
    for (i = 0; i < m; i++)
    {
        arr[i] = malloc(n * sizeof(**arr));
    }
    return arr;
}

void matrx_memory_dealloc(int m, float **array)
{
    int i;
    for (i = 0; i < m; i++)
    {
        free(array[i]);
    }
    free(array);
}

float **transposeMatrix(int m, int n, float **matrix)
{
    float **result = matrx_memory_alloc(n, m);
    for (int i = 0; i < m; i++)
    {
        for (int j = 0; j < n; j++)
            result[j][i] = matrix[i][j];
    }
    return result;
}

int main(void)
{
    float **matrix = matrx_memory_alloc(3, 4);

    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 4; j++)
            matrix[i][j] = (i + j + 1) + ((9 - i - j) / 10.0);
    }

    matrix_print("Initial", 3, 4, matrix);
    float **transpose = transposeMatrix(3, 4, matrix);
    matrix_print("Transpose", 4, 3, transpose);
    matrx_memory_dealloc(4, transpose);
    matrx_memory_dealloc(3, matrix);

    return 0;
}

void matrix_print(const char *tag, int m, int n, float **matrix)
{
    int i, j;

    printf("%s (%d x %d):\n", tag, m, n);
    for (i = 0; i < m; i++)
    {
        char *pad = "[";
        for (j = 0; j < n; j++)
        {
            printf("%s%6.3f", pad, matrix[i][j]);
            pad = ", ";
        }
        printf("%s", " ]\n");
    }
}

它在严格的编译器选项下完全编译:

gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
    -Wold-style-definition -Werror so24276121.c -o so24276121

我注意到valgrind给了它一个干净的健康状况:

==34372== Memcheck, a memory error detector
==34372== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==34372== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==34372== Command: ./so24276121
==34372== 
Initial (3 x 4):
[ 1.900,  2.800,  3.700,  4.600 ]
[ 2.800,  3.700,  4.600,  5.500 ]
[ 3.700,  4.600,  5.500,  6.400 ]
Transpose (4 x 3):
[ 1.900,  2.800,  3.700 ]
[ 2.800,  3.700,  4.600 ]
[ 3.700,  4.600,  5.500 ]
[ 4.600,  5.500,  6.400 ]
==34372== 
==34372== HEAP SUMMARY:
==34372==     in use at exit: 0 bytes in 0 blocks
==34372==   total heap usage: 9 allocs, 9 frees, 152 bytes allocated
==34372== 
==34372== All heap blocks were freed -- no leaks are possible
==34372== 
==34372== For counts of detected and suppressed errors, rerun with: -v
==34372== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

答案 1 :(得分:0)

我不太了解c矩阵,但是你分配的内存将有地址,所以如果你有指向这些地址的指针,你应该能够使用它们的名称解除分配它们。 虽然我希望如果你的函数返回矩阵内存类型,那么它们应该在返回时在每个函数的末尾被删除。我认为普通内存是通过EAX或EAX传递的:EBX组合,它被放置在寄存器中,然后弹回到你的变量或其他东西。但是更大的内存似乎被编码成一个隐藏的指针参数,指向&#34; RETURN&#34;值将由您的函数存储,然后从那里读取内存。 所以你可能更容易使用像这样的结构

matrix *M;

MatrixFunction( matrix* M, int rows, int columns);

MatrixFunction( matrix* M, matrix N, int rows, int columns)

然后编码如下:

invert(Multiply(M,.....)))) 

这样只有一个M可以创建内存而只有一个M来摧毁内存