如何解决在结构中使用 free() for float**两次分配C
我和我的大学正在尝试在 redpitaya(传感器组合)上实现 CNN,因此只有有限的/没有真正的调试选项(通过 UDP 和 LED 发送一些信息)。
我们在使 free()
正常工作时遇到问题。
问题是我们必须使用结构体并且有未定义数量的传入特征。我们想为结构中的错误和其他变量分配内存(到目前为止似乎工作)。但是如果我们尝试使用 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!
最小示例
#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 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 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));
... 为 a
对象分配了足够的空间,其大小为 float
,但您需要为那么多 float *
提供空间。在许多系统上,指针大于 float
。这可以解释您观察到的故障。您可以通过根据接收指针的对象表达所需的大小来避免这种错误:
f_var->error = malloc(a * sizeof(*f_var->error));
当然,这也能适应接收变量类型的变化。
您的 free_func
假定 free()
会以某种方式改变作为参数呈现的对象的值。它不能也不会。在 C 中,所有函数参数都是按值传递的,因此 free()
无法更改其参数的值,即使它想要。除非它一开始为空,否则您不能在之后使用该值,特别是,除非它之前为空,否则您不能期望它为空。如果你想让它为空,那么你需要自己做。此问题将导致您的特定 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;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。