繁体   English   中英

静态指针动态分配缓冲区内的函数

[英]Static pointer to dynamically allocated buffer inside function

我在C中有一个动态分配缓冲区的函数,它被传递给另一个函数来存储它的返回值。 像下面的虚拟示例:

void other_function(float in, float *out, int out_len) {
    /* Fills 'out' with 'out_len' values calculated from 'in' */
}

void function(float *data, int data_len, float *out) {
    float *buf;
    int buf_len = 2 * data_len, i;
    buf = malloc(sizeof(float) * buf_len);

    for (i = 0; i < data_len; i++, data++, out++) {
        other_function(*data, buf, buf_len);
        /* Do some other stuff with the contents of buf and write to *out */
    }
    free buf;
}

function由迭代器在多维数组上调用(确切地说,它是一个NumPy gufunc内核),因此对于data_len ,它被调用数百万次。 一遍又一遍地创建和销毁缓冲区似乎很浪费。 我通常会将缓冲区的分配移动到调用function ,并将poiinter传递给它,但我不直接控制它,所以不可能。 相反,我正在考虑做以下事情:

void function(float *data, int data_len, float *out) {
    static float *buf = NULL;
    static int buf_len = 0;
    int i;
    if (buf_len != 2 * data_len) {
        buf_len = 2 * data_len;
        buf = realloc(buf, sizeof(float) * buf_len); /* same as malloc if buf == NULL */
    }
    for (i = 0; i < data_len; i++, data++, out++) {
        other_function(*data, buf, buf_len);
        /* Do some other stuff with the contents of buf and write to *out */
    }
}

这意味着我永远不会直接释放我分配的内存:它会在后续调用中重用,然后在那里徘徊直到我的程序退出。 这似乎不是正确的事情,但也不是太糟糕,因为分配的内存量总是很小。 我过度担心吗? 有更好的方法吗?

这种方法是合法的(但见下文),尽管像valgrind这样的工具会错误地将其标记为“泄漏”。 (这不是泄漏,因为泄漏是内存使用量的无限增加。)您可能希望准确地确定mallocfree与其他功能相比所耗费的时间。

如果你可以使用C99或gcc,并且你的缓冲区不是太大,你还应该考虑变长数组,它与静态缓冲区一样快(或快),并且不会产生碎片。 如果您使用的是另一个编译器,则可以查看非标准(但广泛 支持的 )alloca扩展。

您需要注意使用静态缓冲区使您的功能:

  1. 线程不安全 - 如果同时从多个线程调用它,它将破坏另一个实例的数据。 如果从numpy调用Python,这可能不是问题,因为GIL会有效地序列化线程。

  2. 非重入 - 如果other_function调用一些最终调用function Python代码 - 无论出于何种原因 - 在function完成之前,你的函数将再次销毁自己的数据。

如果你不需要真正的并行执行和重入,那么static变量的使用就可以了,许多C代码都是这样使用它们的。

这是一种很好的方法,许多库可能会在内部使用这种方法。 程序退出时,内存将自动释放。

您可能希望将buf_len舍入到某个块大小的倍数,因此每次data_len稍微改变时都不会重新realloc() 但是如果data_len几乎总是相同的大小,那么这不是必需的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM