我正在研究的项目涉及一架带有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),但没有太多运气,所以任何意见或建议都会非常感激。
答案 0 :(得分:3)
无法释放内存不会导致分段错误。可能你的问题可能在其他地方。两个可能的条件是:
我的理解是这个记忆 原本应该清理自己了 那不对?
是的,您需要调用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
分配一个新页面,这可能很昂贵。)