【问题标题】:C Matrix function design for chainging and freeing用于链接和释放的 C 矩阵函数设计
【发布时间】:2016-06-06 05:09:13
【问题描述】:

所以目前我正在使用我为一个项目编写的一个小矩阵库,但我讨厌的是我需要使用临时变量来存储指向矩阵的指针以避免内存泄漏

例子:

matrix_t* matrix_add(matrix_t* m1, matrix_t* m2)
{
    assert(m1 != NULL && m2 != NULL);
    assert(m1->rows > 0 && m2->rows > 0 && m1->cols > 0 && m2->cols > 0);
    assert(m1->rows == m2->rows && m1->cols == m2->cols);

    matrix_t* sum = matrix_constructor(m1->rows, m1->cols);

    int i, j;
    for(i=0; i<m1->rows; i++)
    {
        for(j=0; j<m1->cols; j++)
        {
            matrix_set(sum, i, j, matrix_get(m1, i, j) + matrix_get(m2, i, j));
        }
    }
    return sum;
}

如您所见,如果我想像 2 个矩阵相加 (A + B + C) 那样将操作链接在一起,那么我必须执行以下操作:

matrix_t* temp = matrix_add(A, B);
matrix_t* sum = matrix_add(temp, C);
free_matrix(temp);

当存在一长串操作时,这也会变得更加丑陋,因为每个操作都需要一个临时变量。我的问题是,有没有人有任何设计策略可以让我的生活更轻松,代码更简洁,能够链接操作并避免内存泄漏。

我想我可以发送带有可变长度操作的可变长度参数,但是当引入许多不同的操作(如矩阵转置和需要不同大小矩阵的操作)时,这可能会变得混乱。

【问题讨论】:

  • 为matrix_add定义第三个参数作为加法的结果?这样您就可以在两个 matrix_t 变量之间进行 ping pong。 matrix_t r1, r2; matrix_add(A, B, &amp;r1); matrix_add(&amp;r1, C, &amp;r2); matrix_add(&amp;r2, D, &amp;r1); matrix_add(&amp;r1, E ,&amp;r2);等
  • 该解决方案并不能解决问题。我仍然必须在函数之外释放矩阵,并且在某些情况下我需要超过 2 个临时变量。矩阵加法并不是唯一需要链接的情况。
  • 我个人认为调用函数来获取或设置矩阵元素有点过分。如果你愿意支付这么高的成本,那么我建议使用像 Python 这样的非编译语言。在 C 语言中这样做的唯一原因是为了速度,而您正在放弃这种优势。
  • 问题是我正在为一堂课写它,我稍后会并行化它,所以作业的重点是学习。此外,代码将在 OpenMP、OpenMPI 和 Cuda 中并行化,它们都是 C 的副产品。你说得对,使用 getter 和 setter 是多余的,但我将来可以将它们变成宏,我只是不想处理就是现在。
  • 传入一个matrix_t数组如何让函数一次性完成整个链?

标签: c matrix memory-leaks chaining


【解决方案1】:

一种解决方案是实现内存池管理器。分配内存时,主管将指针存储在列表中。当需要清理时,主管释放其列表中的所有内存。

顶级代码看起来像这样

mempool_t *pool = pool_create();
matrix_t *temp, *sum;
temp = matrix_add(pool, A, B);
temp = matrix_add(pool, temp, C);
temp = matrix_add(pool, temp, D);
sum  = matrix_add(pool, temp, E);
pool_destroy(pool, sum);
// ...
// use sum for something
// ... 
free(sum);

pool_create 函数创建一个数据结构来跟踪所有内存分配。这可以是一个链表,也可以是一个可调整大小的数组。

matrix_add 函数将pool 传递给构造函数

matrix_t *sum = matrix_constructor(pool, m1->rows, m1->cols);

matrix_constructor 将分配的内存添加到池中

matrix_t *ptr = malloc(...);
pool_add(pool, ptr);

pool_destroy 函数对列表中的每个指针调用 free,但作为第二个参数传递的指针除外。所以在示例中,sum 没有被释放,必须稍后由顶层代码释放。

【讨论】:

  • 我喜欢这个想法作为清理代码的潜在方法......它还允许我将它们链接在一起,如 matrix_add(pool, matrix_add(pool, A, B), C);
  • @BrianCrafton 哦,是的,这是真的,没想到这一点,但这应该可以。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-16
相关资源
最近更新 更多