释放 C 库中的静态结构

发布于 2024-11-02 01:25:04 字数 903 浏览 5 评论 0原文

我正在从事的一个项目涉及飞行器,其 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

彩虹直至黑白 2024-11-09 01:25:04

未能释放内存不会导致分段错误。您的问题可能出在其他地方。两种可能的情况是:

  1. 缓冲区溢出
  2. 使用指向先前已释放的内存的指针。
  3. 使用错误的指针值,不知何故设置不正确。
  4. 尝试释放 malloc 未返回的指针(或已释放)

我的理解是这段记忆
本来应该清理自己的,是
那不正确吗?

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


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

这段代码的声明是有问题的。 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:

  1. Overflowing a buffer
  2. Using a pointer to memory that has previously been free'd.
  3. Using a bad pointer value, somehow set incorrectly.
  4. Trying to free a pointer not returned by malloc'd (or already free'd)

My understanding was that this memory
was supposed to clean itself up, is
that incorrect?

Yes, you need to call free() to release the memory back to the heap. I would also suggest that you set the pointer value to null after the free, this may help you catch condition 2, from above.


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

This code statement is questionable. What is Nav_str type? Are you sure you don't mean to use strlen(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.

夜清冷一曲。 2024-11-09 01:25:04

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

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

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

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

... 并使用 < 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 return NULL).

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:

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

... and use Nav_IN_OUT.field instead of Nav_IN_OUT_ptr->field, and &Nav_IN_OUT in place of Nav_IN_OUT_ptr (if you are directly passing the pointer value to other functions).

月寒剑心 2024-11-09 01:25:04

我的理解是该内存应该自行清理,这是不正确的吗?

抱歉,但你错了。 :) 使用 malloc() 分配的内存将持续存在,直到您使用 free() 手动删除它。 (你最终确实做对了。万岁。:)

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

这是释放内存的正确方法,但它可能不在正确的位置。一般来说,尝试在编写 malloc() 调用的同时编写 free() 调用。

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

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

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

除了 C 没有给出分段错误之外,是否还有其他原因导致分段错误
在最后一次调用后正确地增加了内存,或者Matlab没有正确地管理其内存?

肯定有可能;也许此内存返回得太快,也许某个指针被 free()ed 两次或更多次,或者您正在覆盖缓冲区(即 malloc(sizeof(Nav_str))< /code> 调用有点令人担忧;根据您平台上的指针大小,它可能只是分配 48 字节;然后将其替换为 >strlen(),请注意 strlen() 不会在字符串末尾为 NUL 字节留出空间; +1); 是为字符串分配内存的常用模式,每当我没有在调用中看到 +1 时我都会感到担心.)

使用 valgrind 一段时间无疑会有助于发现内存错误,也许使用 Electric Fence 一段时间会有所帮助。 valgrind 肯定是更新的,并且肯定可以更好地处理“大型”程序(因为电围栏将为每个 malloc() 分配一个新页面,所以它可能会很昂贵)。

My understanding was that this memory was supposed to clean itself up, is that incorrect?

Sorry, but you were incorrect. :) Memory allocated with malloc() will persist until you manually remove it with free(). (You did get this right in the end. Hooray. :)

Is this the correct way to free this memory? Can I free this memory?

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 your malloc() 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 calls malloc() 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 the free() calls into a foo_destroy() or foo_free() or similar routine. All your callers then need to balance the foo_init() and foo_free() calls. This would be especially appropriate if you can't just write the foo_init() and foo_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.

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?

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 (that malloc(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 with strlen(), note that strlen() won't leave space for a NUL 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 every malloc(), it can be expensive).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文