在C库中释放静态结构

时间:2011-04-19 00:28:07

标签: c matlab static structure mex

我正在研究的项目涉及一架带有GNC代码的飞行器,该代码用C库(.out)编写。我们必须以.out库的形式从LabVIEW(主要航空电子软件)中调用此C代码,并且软件的性质需要静态指针来在对函数的连续调用之间存储数据。我们在整个航班中定期调用GNC执行功能。我现在正试图在Windows上的DLL中使用Matlab MEX包装器来调用此函数,这已经发现了一些内存管理问题。

我在函数开头声明了这样的结构:

static Nav_str *Nav_IN_OUT_ptr;
static  hguid_ref *Guid_IN_OUT_ptr;
static  HopControl *Control_IN_OUT_ptr;

Nav_IN_OUT_ptr = (Nav_str *)malloc(sizeof(Nav_str));
Guid_IN_OUT_ptr = (hguid_ref *)malloc(sizeof(hguid_ref));
Control_IN_OUT_ptr = (HopControl *)malloc(sizeof(HopControl));

这在每次运行期间都会发生。但是,在多次迭代调用此函数后,它在尝试退出后总是因内存分段错误而崩溃。我的理解是,这个记忆应该自我清理,这是不正确的吗?

为了手动清理它,我将这些行添加到最后,仅在清理迭代时调用:

free(Nav_IN_OUT_ptr);
free(Guid_IN_OUT_ptr);
free(Control_IN_OUT_ptr);

这是释放此内存的正确方法吗?我可以释放这段记忆吗?除了C在最后一次调用后没有正确放弃内存,或者Matlab没有正确管理其内存之外,还有另一个原因导致分段错误吗?我已经搜索过一个有类似问题的人(甚至联系Mathworks),但没有太多运气,所以任何意见或建议都会非常感激。

3 个答案:

答案 0 :(得分:3)

无法释放内存不会导致分段错误。可能你的问题可能在其他地方。两个可能的条件是:

  1. 溢出缓冲区
  2. 使用指向以前已免费的内存的指针。
  3. 使用错误的指针值,以某种方式设置不正确。
  4. 尝试释放malloc未返回的指针(或已经免费)

  5.   

    我的理解是这个记忆   原本应该清理自己了   那不对?

    是的,您需要调用free()将内存释放回堆中。我还建议您在空闲后将指针值设置为null,这可以帮助您从上面捕获条件2。


    Nav_IN_OUT_ptr = (Nav_str *)malloc(sizeof(Nav_str));
    

    此代码声明值得怀疑。什么是Nav_str类型?您确定不想使用strlen(Nav_str)+1吗?


    我还需要问一下让指针变为静态的目的是什么?静态函数变量基本上是全局变量,仅在极少数情况下使用。

答案 1 :(得分:2)

您的代码确实存在内存泄漏 - 每次调用该函数时都会分配该内存。即使你当前的方法仍然有内存泄漏 - 如果你只调用free()一次,在最后一次迭代中,那么你只释放了最新的分配。

但是,内存泄漏通常不会导致分段错误(除非您的内存泄漏耗尽所有可用内存,导致后续malloc()次调用返回NULL。)

如果您希望静态结构只分配一次并重复使用,则根本不需要使用malloc() - 您只需将声明更改为:

static Nav_str Nav_IN_OUT;
static hguid_ref Guid_IN_OUT;
static HopControl Control_IN_OUT;

...并使用Nav_IN_OUT.field代替Nav_IN_OUT_ptr->field&Nav_IN_OUT代替Nav_IN_OUT_ptr(如果您直接将指针值传递给其他函数)。< / p>

答案 2 :(得分:1)

  

我的理解是这个记忆应该自我清理,这是不正确的吗?

抱歉,但你错了。 :)使用malloc()分配的内存将一直保留,直到您使用free()手动删除它。 (你确实最终得到了这个.Hooray。:)

  

这是释放此内存的正确方法吗?我可以释放这段记忆吗?

是释放内存的正确方法,但它可能不在正确的位置。一般情况下,尝试在编写free()电话的同时编写malloc()来电。

也许您在函数的开头分配,然后在函数结束时释放。 (在这种情况下,如果内存仅由原始函数调用的函数使用,则堆栈内存使用可能会更好。)

也许您有foo_init()函数调用malloc()并从API创建关联的上下文,然后将该上下文传递到对该数据进行操作的其他例程,然后您需要放置{ {1}}调用free()foo_destroy()或类似例程。然后,您的所有呼叫者都需要平衡foo_free()foo_init()来电。如果您不能只在一个函数中编写foo_free()foo_init()调用,这将特别合适;比如,您可能需要在较大的事件循环中的某个随机点删除您的对象。

也许数据应该只分配一次并永远存在。对于某些应用程序设计而言,这是正确的,并且很难从变量名称中判断这些数据块是否应该永久存在。

  

除了C没有给出之外,还有另一个原因导致分段错误   在最后一次调用后正确启动内存,或者Matlab没有正确管理其内存?

肯定会有;也许这个内存很快就会返回,也许某些指针被foo_destroy()编辑两次或更多次,或者你正在覆盖你的缓冲区(free()调用有点令人担忧;它可能只是分配根据平台上的指针大小,四个八个字节;在用malloc(sizeof(Nav_str))替换之前,请注意strlen()不会在字符串的末尾为strlen()字节留出空间; NUL是为字符串分配内存的常用模式,每当我时我都会担心在通话中看到malloc(len+1);。)

+1的某些时间无疑会帮助找到内存错误,也许有一段时间使用Electric Fence可能有所帮助。 valgrind绝对是新的,绝对可以更好地处理“大型”程序(因为电围栏将为每个valgrind分配一个新页面,这可能很昂贵。)