释放 C 库中的静态结构
我正在从事的一个项目涉及飞行器,其 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),但运气不佳,因此任何评论或建议将不胜感激。
A project I am working on involves a flight vehicle with GNC code written in a C library (.out). We must call this C code from LabVIEW (the primary avionics software) in the form of a .out library, and the nature of the software requires static pointers to store data between successive calls to the function. We call the GNC executive function at regular intervals throughout a flight. I'm now trying to call this function using a Matlab MEX wrapper in a DLL on Windows, and this has uncovered some memory management issues.
I am declaring the structures at the beginning of the function like this:
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));
This happens during every run of the function. However, after this function is called iteratively several times, it always crashes with a memory segmentation fault after it tries to exit. My understanding was that this memory was supposed to clean itself up, is that incorrect?
In order to clean it up manually, I added these lines to the end, to be called only on a clean-up iteration:
free(Nav_IN_OUT_ptr);
free(Guid_IN_OUT_ptr);
free(Control_IN_OUT_ptr);
Is this the correct way to free this memory? Can I free this memory? Might there be another reason for the segmentation error other than C not giving up the memory properly after the last call, or Matlab not properly managing its memory? I've searched all over for someone with a similar problem (even contacting Mathworks) without much luck, so any comments or suggestions would be much appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
未能释放内存不会导致分段错误。您的问题可能出在其他地方。两种可能的情况是:
是的,您需要调用
free()
将内存释放回堆。我还建议您在释放后将指针值设置为 null,这可能会帮助您捕获上面的条件 2。这段代码的声明是有问题的。
Nav_str
类型是什么?您确定不想使用strlen(Nav_str)+1
吗?我还想问一下,你的指针静态化的目的是什么?静态函数变量基本上是全局变量,仅在极少数情况下使用。
Failing to free memory is not going to cause a segmentation fault. It's probably likely your problem lies somewhere else. The two likely conditions are:
Yes, you need to call
free()
to release the memory back to the heap. I would also suggest that you set the pointer value tonull
after the free, this may help you catch condition 2, from above.This code statement is questionable. What is
Nav_str
type? Are you sure you don't mean to usestrlen(Nav_str)+1
?I also need to ask what is the purpose for making your pointers static? Static function variables are basically globals, and only to be used in rare cases.
您的代码确实存在内存泄漏 - 每次调用该函数时都会分配该内存。即使您当前的方法仍然存在内存泄漏 - 如果您在最终迭代中仅调用一次 free(),那么您仅释放了最近的分配。
但是,内存泄漏通常不会导致分段错误(除非内存泄漏耗尽了所有可用内存,导致后续
malloc()
调用返回NULL
)。如果您希望拥有仅分配一次并重复使用的静态结构,则根本不需要使用
malloc()
- 您只需将声明更改为:... 并使用 < code>Nav_IN_OUT.field 代替
Nav_IN_OUT_ptr->field
,并使用&Nav_IN_OUT
代替Nav_IN_OUT_ptr
(如果您是直接将指针值传递给其他函数)。Your code does have a memory leak - it is allocating that memory each time the function is called. Even your current method still has the memory leak - if you only call
free()
once, in the final iteration, then you have only freed the most recent allocation.However, a memory leak will not generally cause a segmentation fault (unless your memory leak exhausts all available memory, causing subsequent
malloc()
calls to returnNULL
).If you wish to have static structures that are only allocated once and re-used, you do not need to use
malloc()
at all - you can simply change your declarations to:... and use
Nav_IN_OUT.field
instead ofNav_IN_OUT_ptr->field
, and&Nav_IN_OUT
in place ofNav_IN_OUT_ptr
(if you are directly passing the pointer value to other functions).抱歉,但你错了。 :) 使用
malloc()
分配的内存将持续存在,直到您使用free()
手动删除它。 (你最终确实做对了。万岁。:)这是释放内存的正确方法,但它可能不在正确的位置。一般来说,尝试在编写
malloc()
调用的同时编写free()
调用。也许您在函数开始时分配,然后在函数结束时释放。 (在这种情况下,如果内存仅由原始函数调用的函数使用,则堆栈内存使用可能会更好。)
也许您有一个调用
的
并从 API 创建关联的上下文,然后将该上下文传递到对该数据进行操作的其他例程中,然后需要将foo_init()
函数malloc()free()
调用放入 < code>foo_destroy() 或foo_free()
或类似的例程。然后,所有调用者都需要平衡foo_init()
和foo_free()
调用。如果您不能只在一个函数中编写foo_init()
和foo_destroy()
调用,那么这将特别合适;比如说,您的对象可能需要在较大的事件循环中的某个随机点被删除。也许数据应该只分配一次并永远存在。这对于某些应用程序设计来说是正确的,并且仅从变量名称很难判断这些数据块是否应该永远存在。
肯定有可能;也许此内存返回得太快,也许某个指针被
free()
ed 两次或更多次,或者您正在覆盖缓冲区(即malloc(sizeof(Nav_str))< /code> 调用有点令人担忧;根据您平台上的指针大小,它可能只是分配 4 或 8 字节;然后将其替换为
是为字符串分配内存的常用模式,每当我没有在调用中看到>strlen()
,请注意strlen()
不会在字符串末尾为NUL
字节留出空间; +1);+1
时我都会感到担心.)使用 valgrind 一段时间无疑会有助于发现内存错误,也许使用 Electric Fence 一段时间会有所帮助。
valgrind
肯定是更新的,并且肯定可以更好地处理“大型”程序(因为电围栏将为每个malloc()
分配一个新页面,所以它可能会很昂贵)。Sorry, but you were incorrect. :) Memory allocated with
malloc()
will persist until you manually remove it withfree()
. (You did get this right in the end. Hooray. :)That is the correct way to free the memory, but it might not be in the correct place. In general, try to write your
free()
calls the same time you write yourmalloc()
calls.Maybe you allocate at the start of a function and then free at the end of the function. (In that case, on-stack memory use might be better, if the memory is only ever used by functions called by the original function.)
Maybe you have a
foo_init()
function that callsmalloc()
and creates associated contexts from an API, then you pass that context into other routines that operate on that data, and then you need to place thefree()
calls into afoo_destroy()
orfoo_free()
or similar routine. All your callers then need to balance thefoo_init()
andfoo_free()
calls. This would be especially appropriate if you can't just write thefoo_init()
andfoo_destroy()
calls in one function; say, your objects might need to be removed at some random point in a larger event loop.And maybe the data should just be allocated once and live forever. That would be correct for some application designs, and it's tough to tell just from the variable names whether or not these blocks of data should live forever.
There sure could be; perhaps this memory is being returned too soon, perhaps some pointer is being
free()
ed two or more times, or you're overwriting your buffers (thatmalloc(sizeof(Nav_str))
call is a little worrying; it is probably just allocating four or eight bytes, based on the pointer size on your platform; and before you replace it withstrlen()
, note thatstrlen()
won't leave space for aNUL
byte at the end of the string;malloc(len+1);
is the usual pattern for allocating memory for a string, and I get concerned any time I don't see that+1
in the call.)Some time with
valgrind
would doubtless help find memory errors, and maybe some time with Electric Fence could help.valgrind
is definitely newer, and can definitely handle 'large' programs better (since electric fence will allocate a new page for everymalloc()
, it can be expensive).