微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在结构中使用 free() for float**两次分配C

如何解决在结构中使用 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 举报,一经查实,本站将立刻删除。