对结构(两个分配)C中的float**使用free()



我和我的研究院正试图在火龙果上实现CNN(传感器组合(,因此只有有限的/没有真正的调试选项(通过UDP和LED发送一些信息(。我们在让free()工作方面遇到了问题。问题是,我们必须使用structs,并且有大量未定义的传入特性。我们希望为结构中的错误和其他变量分配内存(到目前为止似乎有效(。但是,如果我们试图使用free()释放分配的内存,程序就会崩溃。我不知道如何正确地将存储在name_t.error[i]中的参数(?(传递给free()。我们尝试了&*[]的几种组合,但都不起作用。我们不是IT专业的学生,所以这有点超出了我们的能力。

#define a
//global
struct {
...
float** error;
...
} name_t;
name_t var;
main()
init(name_t* f_var, int s1, int s2)
{
//s1 and s2 not used in the example
...
f_var->error = (float**)malloc(a*sizeof(float));
...
for(){
f_var->error[i]=(float*)malloc(b*sizeof(float));
...
}
}
//free() ?
free_func(name_t* f_var)
{
for()
{
free(f_var->error[i]);
...
}
free(f_var->error);
}
//no debugging possible!

最小Exmample

#define a 2
//global
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
typedef struct {
int i;
float** error;
} name_t;
name_t var;
int init(name_t* f_var, int s1, int s2);
int free_func(name_t* f_var);
int main()
{
int x;
x = init(&var, 1,1);
free_func(&var);
return 0;
}
int init(name_t* f_var, int s1, int s2)
{
//s1 and s2 not used in the example
f_var->error = (float**)malloc(a*sizeof(float));
//b an array for the layersize which differs for each layer
for(int i=0; i<a;i++){
f_var->error[i]=(float*)malloc(b[i]*sizeof(float)); 
}
for(int j=0;j<a;j++)
{
for(int k=0;k<b;k++)
{
f_var->error[j][k]=((float)rand() / RAND_MAX - 0.5);
}
}
return 0;
}
//free() ?
int free_func(name_t* f_var)
{
for(int i=0; i<b;i++)
{
free(f_var->error[i]);
if (f_var->error[i]!=NULL)return -1;
}
free(f_var->error);
//if (f_var->error!=NULL)return -1; not needed
return 0;
}

这里有一个错误:

f_var->error = (float**)malloc(a*sizeof(float));

应该是

f_var->error = (float**)malloc(a*sizeof(float*));

如果sizeof(float*)为8,则仅分配所需内存的一半,从而在访问另一半时导致崩溃。

一些提示:

  • 不要强制转换malloc((的结果
  • 使用sizeof *XXX,其中XXX被分配变量,当f_var->error的类型发生变化时,这将有所帮助
f_var->error = malloc(a * sizeof *f_var->error);

通过使用指针数组数据结构而不是数组,使内存分配和释放变得更慢、更大、更复杂。这本身并不是造成问题的原因,但它所需要的更复杂的代码确实为错误留出了更多的空间。

您正在铸造malloc()的返回值。这在C中是不必要的,而且它可能会掩盖错误。不要这样做。事实上,任何非算术目的的强制转换都有一些代码味道。尽管如此,这也不是你的问题的原因。

您没有检查分配失败。这可能与您的问题有关,但这更有可能导致init()中的失败,而不是free_func()中的失败。

f_var->error的顶级分配可能分配的空间不足。这

f_var->error = (float**)malloc(a*sizeof(float));

。。。为float大小的a对象分配足够的空间,但您需要为那么多float *分配空间。在许多系统上,指针大于floats。这可以解释您观察到的故障。您可以通过用接收指针的对象来表示所需的大小来避免这种错误:

f_var->error = malloc(a * sizeof(*f_var->error));

当然,这对于接收变量类型的变化也是有弹性的。

您的free_func假设free()将以某种方式更改作为其参数显示的对象的值。它不能也没有。在C中,所有函数参数都是按值传递的,因此free()即使愿意也不能更改其参数的值。除非值一开始是null,否则不能在之后使用该值,特别是,除非之前是null,不然不能期望它是null。如果你想让它无效,那么你需要自己去做。此问题将导致您的特定free_func提前终止,而不会释放所有内容。这可能会造成内存泄漏,这可能与故障有关。


假设在完整的代码中,b确实是一个扩展为常量表达式的宏,我建议使用以下方法:

#include <stdlib.h>
#define b 4
// ...
typedef struct {
int i;
float (*error)[b]; // array of arrays style
} name_t;
// ...
int init(name_t* f_var, int s1, int s2) {
// only one malloc needed
f_var->error = malloc(a * sizeof(*fvar->error));
if (!f_var->error) return 1;  // malloc failed
for (int j = 0; j < a; j++) {
for (int k = 0; k < b; k++) {
f_var->error[j][k] = ((float)rand() / RAND_MAX - 0.5);
}
}
return 0;
}
int free_func(name_t* f_var) {
// only one free needed
free(f_var->error);
fvar->error = NULL;
return 0;
}

最新更新