4

障害が発生した場合にクリーンアップする必要があるリソースを割り当てた後、 lua_pushstring を使用したい場合があります。ただし、ドキュメントが暗示しているように見えるように、 lua_push* 関数は常にメモリ不足の例外で終了する可能性があります。しかし、その例外は私の C スコープを即座に終了し、エラーの場合に解放する必要があるかもしれない一時的に割り当てた可能性のあるものをクリーンアップすることを許可しません。

状況を説明するコード例:

void* blubb = malloc(20);
...some other things happening here...
lua_pushstring(L, "test"); //how to do this call safely so I can still take care of blubb?
...possibly more things going on here...
free(blubb);

そのような例外が発生するかどうかを事前に確認し、自分のリソースを安全にクリーンアップしたらすぐにプッシュして自分のエラーをトリガーするのを避ける方法はありますか? または、どうにかして setjmp を非アクティブ化し、プッシュを行った後に「魔法の変数」をチェックして、実際に機能したか、エラーが発生したかを確認できますか?

自分の関数をpcallすることも考えましたが、pcallで安全に呼び出したい関数をスタックにプッシュしただけでも、メモリ不足になる可能性がありますね。

明確にするために、Lua が過剰なメモリを割り当てるのを防ぐカスタム メモリ アロケータと組み合わせて使用​​することを具体的にお願いしているので、システム全体でメモリが不足している場合ではないと仮定します。

4

3 に答える 3

2

Lua 状態を作成したときにユーザー定義のメモリ ハンドラーを Lua に登録していない限り、メモリ不足エラーが発生すると、アプリケーション全体がメモリ不足になったことを意味します。通常、この状態からの回復は不可能です。または、少なくとも、多くの場合、実現不可能です。アプリケーションに依存する可能性がありますが、おそらくそうではありません。

要するに、それが起こった場合、あなたはもっと大きなことを心配する必要があります;)

あなたに影響を与える唯一の種類のクリーンアップは、アプリケーションの外部のものです。いくつかの状態を解放または設定する必要があるプロセスグローバルメモリがある場合。プロセス間通信を行っており、話しているメモリマップファイルがあります。またはそのようなもの。

それ以外の場合は、プロセスを強制終了することをお勧めします。


Lua を C++ ライブラリとしてビルドできます。これを行うと、エラーは実際の例外になり、キャッチするか、RAII オブジェクトを使用して処理することができます。

C で行き詰っている場合は...まあ、できることはあまりありません。

Lua が大量のメモリを消費するのを避けるために、はるかに早くメモリ不足になるカスタム アロケータに特に関心があります。

その後、別の方法で処理する必要があります。メモリ不足のエラーを通知することは、基本的には「Lua を今すぐ終了させたい」ということです。

Lua がメモリを消費するのを防ぐ方法は、Lua の状態のメモリを定期的にチェックし、使用量が多すぎる場合はガベージ コレクションを行うことです。それでも十分なメモリが解放されない場合は、Lua の状態を手動で終了する必要がありますが、安全な場合にのみ終了してください。

于 2012-04-21T23:12:08.180 に答える
0

lua_atpanic()は、実行する必要があるクリーンアップの種類によっては、1 つの解決策になる場合があります。エラーをスローすることはありません。

特定の例では、 blubb を userdata として作成することもできます。その後、Lua はスタックを離れたときに自動的に解放します。

于 2012-04-21T23:01:25.750 に答える
0

私は最近、Lua サンドボックスに再び取り掛かりましたが、以前に受け入れた答えは悪い考えだと思います。私はこれをもう少し考えました:

定期的なチェックだけでは不十分な理由

大量のメモリ消費を定期的にチェックし、「安全な場合にのみ」Lua を終了することは、1 つの巨大なテーブルが1 つの VM 命令で大量のメモリを消費する可能性があることを考えると、悪い考えのように思えます。それが起こった後にのみ見つけてください-あなたのプログラムはすでにそれで死んでいる可能性があり、実際には、そもそもその割り当てを時間内に停止していれば完全に回避できたはずのはるかに大きな問題があります。

Lua にはすでにメモリ不足の優れた例外が組み込まれているため、これを使用したいと思います。これにより、必要最小限のこと (スクリプトがより多くのものを割り当てるのを防ぎ、回復できる可能性があります) を行うことができます。それからCコードが壊れています。

したがって、メモリ制限のあるLuaサンドボックスの現在の計画は次のとおりです。

  • 制限付きで NULL を返すカスタム アロケータを使用する

  • メモリリークやその他の破損なしにこれを処理できるように、すべての C 関数を設計します。

しかし、C 関数を安全に設計するにはどうすればよいでしょうか。

lua_pushstring などは、それが事前に発生するかどうかを知らなくても、常にエラーで jmp を設定できるため、どうすればよいでしょうか? (これはもともと私の質問でした)

私は実用的なアプローチを見つけたと思います:

ポインターを割り当てるときにポインターを登録し、使い終わったら登録を解除する機能を追加しました。これは、Lua が突然、C コードから私を setjmp して、クリーンアップする機会が得られない場合、グローバル リストにすべてを持っていることを意味します。

それは醜いですか?

はい、それはかなりハックです。しかし、それはおそらくうまくいくでしょう。「定期的なチェック」とは異なり、実際には真のハード制限を設定し、積極的な攻撃によるアプリケーション自体の問題を回避することができます。

于 2014-09-08T02:02:42.670 に答える