2

私が取り組んでいるプロジェクトには、Cライブラリ(.out)に記述されたGNCコードを備えた飛行体が含まれます。このCコードをLabVIEW(主要なアビオニクスソフトウェア)から.outライブラリの形式で呼び出す必要があります。ソフトウェアの性質上、関数への連続する呼び出しの間にデータを格納するために静的ポインタが必要です。フライト中、定期的に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に連絡しても)同様の問題を抱えている人を探し回ったので、コメントや提案をいただければ幸いです。

4

3 に答える 3

3

メモリの解放に失敗しても、セグメンテーション違反は発生しません。おそらくあなたの問題はどこかにあるでしょう。考えられる2つの条件は次のとおりです。

  1. バッファのオーバーフロー
  2. 以前に解放されたメモリへのポインタを使用します。
  3. 不正なポインタ値を使用しているため、どういうわけか正しく設定されていません。
  4. mallocによって返されない(またはすでに解放されている)ポインターを解放しようとしています

私の理解では、この記憶はそれ自体をきれいにするはずだったのですが、それは間違っていますか?

free()はい、メモリをヒープに戻すために呼び出す必要があります。また、ポインタ値をnullフリーの後に設定することをお勧めします。これは、上から条件2をキャッチするのに役立つ場合があります。


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

このコードステートメントには疑問があります。タイプとは何Nav_strですか?使うつもりはないのstrlen(Nav_str)+1ですか?


また、ポインタを静的にする目的は何ですか?静的関数変数は基本的にグローバルであり、まれなケースでのみ使用されます。

于 2011-04-19T00:54:47.633 に答える
2

コードにはメモリリークがあります。関数が呼び出されるたびにそのメモリが割り当てられます。現在のメソッドでもまだメモリリークがありますfree()。最後の反復で1回だけ呼び出すと、最新の割り当てのみが解放されます。

ただし、メモリリークによってセグメンテーション違反が発生することは通常ありません(メモリリークによって使用可能なすべてのメモリが使い果たされ、後続の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します(ポインタ値を他の関数に直接渡す場合)。

于 2011-04-19T00:57:57.507 に答える
1

私の理解では、この記憶はそれ自体をきれいにするはずだったのですが、それは間違っていますか?

申し訳ありませんが、あなたは間違っていました。:)で割り当てられたメモリは、malloc()手動で削除するまで存続しますfree()。(あなた最終的にこれを正しく理解しました。やったー。:)

これは、このメモリを解放する正しい方法ですか?このメモリを解放できますか?

これはメモリを解放する正しい方法ですが、正しい場所にない可能性があります。一般的に、あなたがあなたfree()の電話を書くのと同時にあなたの電話を書くようにしてくださいmalloc()

たぶん、関数の開始時に割り当て、関数の終了時に解放します。(その場合、メモリが元の関数によって呼び出された関数によってのみ使用される場合は、スタック上のメモリの使用がより適切になる可能性があります。)

foo_init()APIから関連するコンテキストを呼び出して作成する関数がmalloc()あり、そのコンテキストをそのデータを操作する他のルーチンに渡し、またはまたは同様のルーチンにfree()呼び出す必要がある場合があります。次に、すべての発信者はとのバランスを取る必要があります。これは、と呼び出しを1つの関数で記述できない場合に特に適しています。たとえば、オブジェクトは、より大きなイベントループのランダムなポイントで削除する必要がある場合があります。foo_destroy()foo_free()foo_init()foo_free()foo_init()foo_destroy()

そして、たぶん、データは一度だけ割り当てられ、永久に存続する必要があります。これは一部のアプリケーション設計では正しいでしょう。変数名だけから、これらのデータブロックが永久に存続するかどうかを判断するのは困難です。

Cが最後の呼び出し後にメモリを適切に放棄しなかった、またはMatlabがメモリを適切に管理しなかった以外に、セグメンテーションエラーの別の理由があるのでしょうか。

確かにある可能性があります。このメモリがすぐに返されるか、ポインタがfree()2回以上使用されているか、バッファを上書きしている可能性があります(このmalloc(sizeof(Nav_str))呼び出しは少し心配です。おそらく、ポインタのサイズに基づいて4バイトまたは8バイトを割り当てているだけです。プラットフォーム上で;そしてそれを置き換える前に、文字列の最後にバイト用のスペースを残さないことstrlen()に注意してください;は文字列にメモリを割り当てるための通常のパターンであり、私が見ないときはいつでも心配します通話中のことです。)strlen()NULmalloc(len+1);+1

ある時間valgrindは間違いなくメモリエラーを見つけるのに役立ち、おそらく電気柵のある時間は役立つかもしれません。valgrindは間違いなく新しく、「大規模な」プログラムを確実にうまく処理できます(電気柵はすべてmalloc()に新しいページを割り当てるため、費用がかかる可能性があります)。

于 2011-04-19T01:02:57.147 に答える