gpt4 book ai didi

c - 指向函数内部动态分配缓冲区的静态指针

转载 作者:太空狗 更新时间:2023-10-29 17:10:36 26 4
gpt4 key购买 nike

我在 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 的函数,并将指针传递给它,但我不直接控制它,所以不可能。相反,我正在考虑执行以下操作:

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,并且您的缓冲区不是太大,您还应该考虑可变长度数组,它与静态缓冲区一样快(或更快),并且不会产生碎片。如果您使用的是另一个编译器,则可以查看非标准(但 widely supported )alloca 扩展。

您需要注意使用静态缓冲区会使您的函数:

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

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

如果您不需要真正的并行执行和可重入,那么使用 static 变量就可以了,很多 C 代码都以这种方式使用它们。

关于c - 指向函数内部动态分配缓冲区的静态指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18390951/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com